Contents |
Print out a list of all regular files with full paths:
$ find -type f -printf "`pwd`/%P\n"
Print non-svn files:
$ find -not -regex ".*\.svn.*"
$ printf "echo hej\necho der\n"
echo hej
echo der
$ printf "echo hej\necho der\n" | xargs -i bash -c "{}"
hej \___________________/
der |_ this is a magic spell causing
every line of the input to be
executed in turn
Print a command that prints a linefeed:
$ printf 'printf "\\\\n"\n' printf "\\n"
Print a command that prints "hi":
$ printf "printf \\\"hi\\\"\n" printf \"hi\"
A combination
$ printf "printf \\\"hi \\\"\nprintf \\\"there\\\\\\n\\\"\n"
printf \"hi \"
printf \"there\
\"
$ printf "printf \\\"hi \\\"\nprintf \\\"there\\\\\\n\\\"\n" | xargs -i bash -c "{}"
hi there
... probably one of the hardest ways of printing "hi there" ;)
Single quotes can be used instead for slightly better readability:
$ printf 'printf \"hi\"\n' printf \"hi\"
$ printf 'printf \"\\\n\"\n' printf "\\n"
$ printf 'printf \"hi \"\nprintf \"there\\\n\"\n'|xargs -i bash -c "{}"
$ find -regex ".*\.flac$" -and -not -regex ".*\.flac\.flac" | <- find specific files
sed -re "s/(.*)/\1 \1/" | <- duplicate file name
sed -re "s/(.*) (.*)\.flac/flac -dc \1 | lame -b192 ->\2.mp3/g" | <- construct command-line
and replace extension
xargs -i bash -c "echo {}" <- execute each command
|
remove this to activate
The task in this section is renaming all files in a directory (and potentially all subdirectories). It is a bit tricky because filenames with space tend to ruin the command parsing.
Check out this little beauty using find, awk, and xargs:
$ find | awk '/ / { new = gensub(/ /, "_", "g", $0);
printf("mv -f \\\"%s\\\" \\\"%s\\\"\n", $0, new); }' | xargs -i bash -c "echo {}"
Here it is explained in greater detail:
$ find |
awk '/ / { -> only look at files with spaces (we use awk
for filtering instead of 'find' because awk
uses POSIX regexs)
new = gensub(/ /, "_", "g", $0); -> replace space globally with underscore
printf("mv -f \\\"%s\\\" \\\"%s\\\"\n", $0, new); -> create command - the escaped backslash
and double quote will be correctly expanded
}' | xargs -i bash -c "echo {}" by bash, when executed
|_ remove this to perform changes
For each file, print out 'mv filename filename_with_underscores'
$ for x in *.txt;do (printf "mv $x "|sed 's/ /\\ /g';printf "$x\n"|sed 's/ /_/g')|xargs -i bash -c "echo {}";done
remove this to activate _____|
But 'for' is no good for using and 'find' with filenames with spaces:
$ find -printf '"%p"\n' "." "./one_word" "./two words" $ for f in `find -printf '"%p"\n'`;do echo $f;done "." "./one_word" "./two <- NOT good! words"
remove all lines with '* file version :' in all files in this dir and subdirs
$ for x in `find -name "*.*"`;do sed -e "/\*.*file version.*:/d" $x >$x.sed;mv $x.sed $x; done
remove all lines with '* TODO : ?' in all files in this dir and subdirs
$ for x in `find -name "*.*"`;do sed -e "/\*.*TODO.*: \?/d" $x >$x.sed;mv $x.sed $x; done
find all files called '*CVS/Root' and change '3.80' to '3.80:' in them:
$ for x in `find -regex ".*CVS/Root"`;do sed -e "s/3\.80/3\.80:/" $x >$x.sed;mv $x.sed $x; done
change all date signatures in all files (except CVS files) from old dd/mm/yy to ISO 8601 format
(ccyy/mm/dd):
$ for x in `find -not -regex ".*CVS.*"`; do sed -ri -e "s/([0-9]{2})\/([0-9]{2})\/([0-9]{2})/20\3-\2-\1/g" $x;done
if it is done in a CVS checkout, check the changes with this
$ cvs di|less
I want to rename all files and directories with name containing the danish letters 'æøåÆØÅ' to corresponding files/directories without these characters. The problem with this task is that the directory must be traversed one level at a time (breadth-first) to avoid accessing invalid directory names. This makes it necessary to use a script:
LETTERS="[æøåÆØÅ]+" MAXDEPTH=255
d=1;while [ $d -lt $MAXDEPTH ];do
printf "processing files at level %d... " $d;
# do any files still need to be moved? if find -mindepth $d -name "*"|egrep $LETTERS>/dev/null;then
# list all files with danish letters in this directory tree level
find -mindepth $d -maxdepth $d -name "*"|egrep $LETTERS >/tmp/rename.tmp;
# make a new list with all the danish letters changed
sed -e "s/æ/ae/g" -e "s/ø/oe/g" -e "s/å/aa/g" -e "s/Æ/AE/g" -e "s/Ø/OE/g" -e "s/Å/AA/g" </tmp/rename.tmp >/tmp/rename2.tmp
# move the files
paste /tmp/rename.tmp /tmp/rename2.tmp|xargs -n2 mv
d=$((d+1)); else d=$MAXDEPTH; # we are done with this level fi; printf "done.\n";
done