Assuming a UNIX-like environment:
To handle spaces in names, use the -0
flag to xargs. With find:
find . -name '*.mp3' -print0 | xargs -0 dosomething
Some other commands have various switches for nul-separated output, usually -0
or -z
. If your list is line-oriented, do something like:
cat filelist | tr -s '\012\015' '\000' | xargs -0 dosomething
Which uses tr
to translate newlines and linefeeds to nuls, handling UNIX and DOS (and even Mac Classic) line ends and skipping blank lines.
Don't forget that newlines are valid filename characters on most UNIX-like filesystems.
If dosomething
is complex, you can use bash functions:
dosomething() {
while [ -n "$1" ] ; do
out="$(basename "$1" .mp3).ogg"
convert "$1" "converted/$out"
shift
done
}
export -f dosomething
and invoke xargs
like:
cat filelist | tr -s '\012\015' '\000' | xargs -0 bash -c 'dosomething "$@"' --
Note the judicious use of double-quoting to preserve spaces, and that double-quoted strings can be nested inside double-quoted $()
eval operators.
Within the function, you can write "$@"
to get a properly quoted argument list to pass to a subprocess:
dosomething() {
command1 preargs "$@" postargs | command2
command3 "$@"
}
You can also use read
to work line-by-line:
cat filelist | while read i ; do something "$i" ; done
but xargs gets you all of the args at once.