4

I'm trying to covert all m4a to mp3 my code look like this:

find . -name '*.m4a' -print0 | while read -d '' -r file; do
  ffmpeg -i "$file" -n -acodec libmp3lame -ab 128k "${file%.m4a}.mp3";
done

but it only work for first mp3 file for next it show error:

Parse error, at least 3 arguments were expected, only 1 given in string '<All files in one line>'

Enter command: <target>|all <time>|-1 <command>[ <argument>]

The files contain spaces ampersands and parenthesis.

  • 2
    You could replace ffmpeg with echo -- and inspect the output to ensure all is right. – thecarpy Apr 20 '18 at 12:44
  • set IFS to the null string as well ... |while IFS= read -d '' -r file; ... . You could use all with find instead of using a shell while-loop – αғsнιη Apr 20 '18 at 14:47
  • @thecarpy I was testing with echo and I've got each file with its own ffmpeg – jcubic Apr 20 '18 at 15:33
4

When reading a file line by line, if a command inside the loop also reads stdin, it can exhaust the input file.

Continue reading here: Bash FAQ 89

So the code should look like this:

find . -name '*.m4a' -print0 | while read -d '' -r file; do
  ffmpeg -i "$file" -n -acodec libmp3lame -ab 128k "${file%.m4a}.mp3" < /dev/null
done
0

Your question asked about converting m4a to mp3.

This is a bash script I have been using for a while.

Adjust the avconv command to suite your needs.

#!/bin/bash
## jc 2016
## convert [m4a mp3 wma] to mp3 128k
## [-vn] disable video recording
##
## avconv with lame mp3 plugin
## [-acodec libmp3lame]
##
## 192 k constant bitrate
## [-ab 192k]
## [-ab 128k]
##
## 44.1kHz sampling rate
## [-ar 44100]
##
## 2 channel audio
## [-ac 2]
##

##  force the shell to do a case insensitive comparison
shopt -s nocasematch

working_directory="./mp3_converted"
# check if dir exist
if [ ! -d "$working_directory" ];
then
  # dir does not exist
      echo "convert directory does not exist $working_directory..."
  `mkdir -p "$working_directory"`
       echo "convert directory created $working_directory..."
fi

COUNT=0

for i in *; do

  case $i in
    *.mp3)
      avconv -analyzeduration 999999999 -map_metadata 0 -i "$i" -vn -acodec libmp3lame -ac 2 -ab 128k -ar 44100 "$working_directory/`basename "$i" .mp3`.mp3"
      echo $i
      ;;
    *.m4a)
      ##avconv -analyzeduration 999999999 -map_metadata 0 -i "$i" -vn -acodec libmp3lame -ac 2 -ab 128k -ar 44100 "$working_directory/`basename "$i" .m4a`.mp3"
      # adjusted for ffmpeg to test. 
      ffmpeg -i "$i" -n -acodec libmp3lame -ab 128k "$working_directory/`basename "$i" .m4a`.mp3" 
      echo $i
      ;;
    *.wma)
      avconv -analyzeduration 999999999 -map_metadata 0 -i "$i" -vn -acodec libmp3lame -ac 2 -ab 128k -ar 44100 "$working_directory/`basename "$i" .wma`.mp3"
      echo $i
      ;;
    *)
      echo "other"
      ;;
  esac

done

## back to normal comparison
shopt -u nocasematch
exit 0
0

Why not just use the -exec argument of find? So find -iname '*.m4a' -exec ffmpeg -i {} -n -acodec libmp3lame -ab 128k {}.mp3 \; and run a rename command afterward?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.