3

I'm trying to use ffmpeg to convert some .m4a audio files to .mp3, and have come across something that has me stumped. I'd like to create the .mp3 in the same location and with the same filename as the .m4a, and so I'm using a combination of find/exec and a bash script to do this, as follows:

find /Volumes/Untitled/ -name '[!.]*' -name '*.m4a' -exec ./m4atomp3.sh {} \;

where m4atomp3.sh looks like:

#!/usr/bin/env bash
[[ -f "$1" ]] || { echo "$1 not found" ; exit 1 ; }
P="$1"
echo "$P is the full filename"
filename=${P%.*}
echo "$filename is the stripped filename"
m4afilename=\"$filename.m4a\"
echo "$m4afilename is the input filename"
mp3filename=\"$filename.mp3\"
echo "$mp3filename is the output filename"
mycmd="/Users/nickstyles/Downloads/ffmpeg -i "$m4afilename" -codec:a libmp3lame -qscale:a 2  -nostdin "$mp3filename
echo $mycmd
$mycmd

Whenever I try this, it fails because ffmpeg doesn't find the file, seemingly because of the whitespace in the filename, e.g if the file was called /Volumes/Untitled/My M4As/My M4A.m4a I would see:

ffmpeg version N-99346-g003b5c800f-tessus  https://evermeet.cx/ffmpeg/  Copyright (c) 2000-2020 the FFmpeg developers
  built with Apple clang version 11.0.0 (clang-1100.0.33.17)

[configuration details]

"/Volumes/Untitled/My: No such file or directory

However, if I just paste what is returned by echo $mycmd into the command line, e.g:

/Users/nickstyles/Downloads/ffmpeg -i "/Volumes/Untitled/My M4As/My M4A.m4a" -codec:a libmp3lame -qscale:a 2 -nostdin "/Volumes/Untitled/My M4As/My M4A.mp3"

then it works absolutely fine. I'm sure I'm missing something very obvious, which hopefully someone can spot!

3
  • 1
    Btw.: Paste your script at shellcheck.net and try to implement the recommendations made there. Commented Sep 25, 2020 at 16:33
  • Try this, mycmd="/Users/nickstyles/Downloads/ffmpeg -i $m4afilename -codec:a libmp3lame -qscale:a 2 -nostdin $mp3filename" Commented Sep 25, 2020 at 16:47
  • Storing commands (or even just shell syntax, like quotes) in variables tends not to work well; see BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail! In general, it's best to just execute commands directly rather than trying to store them first. Commented Sep 25, 2020 at 19:20

2 Answers 2

2

As Benjamin W. pointed out the problem was that the variable was still getting split by bash, due to WordSplitting, and the quotes I was adding to the content of the variable were not helping against this. The key was to ensure that the quotes were placed around the variable itself like:

m4afilename=$filename.m4a
echo "$m4afilename is the input filename"
mp3filename=$filename.mp3
echo "$mp3filename is the output filename"
/Users/nickstyles/Downloads/ffmpeg -i "$m4afilename" -codec:a libmp3lame -qscale:a 2  -nostdin "$mp3filename" 

and now this works!

Sign up to request clarification or add additional context in comments.

Comments

1

Try this : mycmd="/Users/nickstyles/Downloads/ffmpeg -i $m4afilename -codec:a libmp3lame -qscale:a 2 -nostdin $mp3filename"

In bash, you can put variable straight into double quotes.

2 Comments

This is still subject to word splitting when running the command as $mycmd; when running as "$mycmd", the whole string is considered the name of the command and it won't be found. See BashFAQ/050
Ah, yes. Indeed it seems I didn't pay enough attention to the bash word splitting rules, thanks for pointing this out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.