2

I'm trying to convert a bunch of .aac files to .mp3 files in separate subdirectories in a directory. This is the code I've written:

for dir in */
do
    OUTPUT_DIR=./mp3
    mkdir "$OUTPUT_DIR"
    for i in *.aac;
      do name=`echo "$i" | cut -d'.' -f1`
      echo "$name"
      ffmpeg -i "$i" -vn -ar 44100 -ac 2 -b:a 192k "$OUTPUT_DIR/${name}.mp3"
    done
done

However this just try to run the commands in the outside directory and gives an error. I'm new at bash so it might be a very simple mistake I'm not seeing.

Yuyan_Li
  • 63
  • 4

2 Answers2

4

How to loop through files in subdirectories?

Read ex How to loop through a directory recursively to delete files with certain extensions

This is the code I've written:

Check your scripts with http://shellcheck.net

Do not use `. Use $(...) instead.

To get file name and dir see basename and dirname commands. Your name=echo "$i" | cut -d'.' -f1 will fail when directory has a dot.

Use printf "%s\n" "$i" or in bash <<<"$i" here string instead echo "$i" |. See ex. https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo .

Prefer lower case variables in your scripts.

so it might be a very simple mistake I'm not seeing.

You are not changing the direcotry at all. You need to cd somewhere to that dir and then cd - back (or pushd + popd). But just reference directories relative to your current dir anyway. Maybe something along:

for dir in ./*/; do
    # create the directory in dir
    output_dir="./$dir/mp3"
    mkdir "$output_dir"
    # find files aac inside $dir/
    for i in "$dir"/*.aac; do
       name=$(basename "$i" .acc)
       echo "$name"
       ffmpeg -i "$i" -vn -ar 44100 -ac 2 -b:a 192k "$output_dir/${name}.mp3"
    done
done
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • 1
    This answer is so detailed and clear, definitely learned something and solved the problem, thank you! – Yuyan_Li Apr 14 '21 at 14:57
2

You may want to use find to recursively find all files in all subdirectories of a directory.

Here's an example (it assumes you also want to recreate the subdirectories in the output directory).

OUTPUT_DIR=./mp3

for item in $(find . -type f -name *.aac); do
    name="$(basename $item .aac)"
    subdir="$(dirname $item)"
    mkdir -p "$OUTPUT_DIR/$subdir"
    ffmpeg -i "$name" -vn -ar 44100 -ac 2 -b:a 192k "$OUTPUT_DIR/$subdir/$name.mp3"
done
Czaporka
  • 2,190
  • 3
  • 10
  • 23