2

currently, I run this command...

# Script designed to convert webm files to m4a for easy listening

for i in *.m4a ; do
    echo ffmpeg -i "\""$PWD/$i"\"" -c:a copy "\""$PWD/${i%.m4a}.mkv"\"" >> ~/bulk.command.txt
done

to create myself a script file that I can later run to do batch repackages of media files. Sadly this process requires me to enter each directory that needs to be repackaged and have me type the scripts name.

Sometimes these projects have quite a few directories as well as subdirectories. Also these projects when getting big, are requiring me to really be careful on the size of the projects root dir.

I am still learning how to code in bash, and this simple script took me quite some time to perfect to make sure just about every possible file name is accounted for.

What I would like to do next is modify it in such as way as I can simply go into my home folders music folder, run this command a single time AND also have it save the directory layout, but also place the files ffmpeg creates into a different directory. Do any wizards out there have some code examples, or terms, or ideas how I can accomplish this task?

  • Just bash? python is doing a nice job on this. – Jacob Vlijm Apr 5 '17 at 6:16
  • Consider adding -map 0 if you want to stream copy all streams from the input; otherwise the ffmpeg default stream selection behavior will choose only one stream per stream type. For example, if there are two audio streams it will by default only copy one. Although, it is unlikely that M4A has more than one stream per type. – llogan Apr 5 '17 at 18:57
  • I am not opposed to using another language to do this, I just don't know python, and learning new skills for me is difficult because of a disability... – Monery Apr 7 '17 at 0:34
3

Enable recursive globbing to recurse into subdirectories:

shopt -s globstar

Then you could do:

for f in **/*.m4a
do
    printf 'ffmpeg -i %q -c:a copy %q\n' "$PWD/$f" "$PWD/${f%.m4a}.mkv"
done > bulk.command.txt

printf's %q quotes strings so that they can be safely used as shell input, so you don't have to mess with quotes there:

  %q    quote the argument in a way that can be reused as shell input

If you make this a script, then you can use arguments to decide whether to use a different directory for the output files:

#! /bin/bash
shopt -s globstar

for f in **/*.m4a
do
    printf 'ffmpeg -i %q -c:a copy %q\n' "$PWD/$f" "${1:-$PWD}/${f%.m4a}.mkv"
done > bulk.command.txt

${foo:-bar} uses the the value of variable foo, if it is not empty, or bar otherwise, so in this case it uses the first argument if not empty and $PWD otherwise.

You'll need to recreate the directory structure in that case, which can be done with mkdir -p:

#! /bin/bash
shopt -s globstar

for f in **/*.m4a
do
    printf 'mkdir -p %q\n' "${1:-$PWD}/${f%/*}"
    printf 'ffmpeg -i %q -c:a copy %q\n' "$PWD/$f" "${1:-$PWD}/${f%.m4a}.mkv"
done > bulk.command.txt

That's if you really need to create a script for later usage. Personally, I don't see the point - you could just run the loop directly when you actually need to run it:

#! /bin/bash
shopt -s globstar

for f in **/*.m4a
do
    mkdir -p "${1:-$PWD}/${f%/*}"
    ffmpeg -i "$PWD/$f" -c:a copy "${1:-$PWD}/${f%.m4a}.mkv"
done > bulk.command.txt
  • thanks for the wonderful feedback, I will try to read it again later when my mind wishes to cooperate with learning and reading. I'll let ya know if this does what I am looking to accomplish – Monery Apr 7 '17 at 0:48

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.