4

I want the following loop to go through m4a files AND webm files. At the moment I use two diffrent loops, the other one just replaces all the m4a from this loop. Also the files that ffmpeg outputs should remove a m4a extension if it was a m4a file, and a webm extension if it was a webm file. And replace that with mp3. (As it does here with m4a). I have no Idea how to do it, I think it has something to do with regex expressions, but I have no idea how really use them nor have I ever found a good tutorial/documentation, so if you have one, please link it aswell.

for i in *.m4a ; do
        echo "Converting file $converted / $numfiles : $i"
        ffmpeg -hide_banner -loglevel fatal -i "$i" "./mp3/${i/.m4a}.mp3"
        mv "$i" ./done
        converted=$((converted + 1))
done
usbpc102
  • 1,137
  • 13
  • 25
  • Possible duplicate of [Matching files with various extensions using for loop](https://stackoverflow.com/q/6223817/608639), [for loop for multiple extension and do something with each file](https://stackoverflow.com/q/12259331/608639), [Loop over multiple file extensions from bash script](https://stackoverflow.com/q/49103942/608639), etc. – jww Aug 19 '18 at 06:44

1 Answers1

8

Try the following:

for i in *.m4a *.webm; do
  echo "Converting file $converted / $numfiles : $i"
  ffmpeg -hide_banner -loglevel fatal -i "$i" "./mp3/${i%.*}.mp3"
  mv "$i" ./done
  converted=$((converted + 1))
done
  • You can use for with multiple patterns (globs), as demonstrated here: *.m4a *.webm will expand to a single list of tokens that for iterates over.

    • You may want to add shopt -s nullglob before the loop so that it isn't entered with the unexpanded patterns in the event that there are no matching files.
  • ${i%.*}.mp3 uses parameter expansion - specifically, % for shortest-suffix removal - to strip any existing extension from the filename, and then appends .mp3.

Note that the techniques above use patterns, not regular expressions. While distantly related, there are fundamental differences; patterns are simpler, but much more limited; see pattern matching.

P.S.: You can simplify converted=$((converted + 1)) to (( ++converted )).

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • That works. But I'm pretty sure it would break if the filename contains mode then one `.` here `${i%.*}` . Is there a way that it won't break, or am I wrong? – usbpc102 Dec 20 '15 at 14:46
  • 1
    @usbpc102: No, it won't break, because `%` is used for _shortest_ suffix matching (it _would_ break if you used `%%` for _longest_ suffix matching instead). Try it yourself: `i='one.two.m4a'; echo "${i%.*}"` – mklement0 Dec 20 '15 at 14:48