For loop with unix find
That's one of the reasons why you never use a for
loop to iterate over a command whose output can contain spaces. Especially if that output is a list of file names that can contain anything except /
and \0
. You have fallen into bash pitfall number 1. Always use while
instead. To make sure it works with all file names, including those with spaces, newlines, tabs, backslashes or any other strange characters, use this:
find /home/family/Music -name '*.m4a' -print0 | while IFS= read -r -d '' file; do
ffmpeg -i "$file" -acodec libvorbis -aq 6 -vn -ac 2 "${file%.m4a}.ogg";
done
Explanation
Note that I quoted
*.mp4a
which ensures that bash will not expand it before passing it tofind
. This is important for the cases where you have files that match that glob in your current directory.The
-print0
, as you probably know, causesfind
to separate its results with\0
instead of newlines.IFS=
: This sets the input field character to nothing, ensuring that no word splitting will take place.-
while read -r -d '' file
: This will iterate over the results, saving each as$file
, just likefor file in $(command)
. The options are (fromhelp read
):-r do not allow backslashes to escape any characters -d delim continue until the first character of DELIM is read, rather than newline
Setting the delimiter to the empty string (
-d ''
) makesread
play nice with find's-print0
. "${file%.mp3}.ogg";
: This is simply to remove the.m4a
suffix and replace it with.ogg
so you getfoo.ogg
instead offoo.m4a.ogg
.
The rest is the same as you had attempted so I'm guessing you understand it.
Use xargs
with -0
option, or use find
's own exec
option:
find /home/family/Music -name '*.m4a' -exec ffmpeg -i "{}" -acodec libvorbis -aq 6 -vn -ac 2 "{}.ogg" \;
# or:
find /home/family/Music -name '*.m4a' -print0 | xargs -0 -i ffmpeg -i {} -acodec libvorbis -aq 6 -vn -ac 2 {}.ogg
Note that in both cases (and in your original command), x.m4a
will be converted to x.m4a.ogg
.
This may be solution of what you want
#!/bin/bash
find /home/family/Music -type f -name '*.m4a' -print0 | while IFS= read -r -d '' i;
do
#do ffmpeg -i "$i" -acodec libvorbis -aq 6 -vn -ac 2 "$i.ogg";
echo $i
done