3

Using mkvmerge, I want to add audio tracks to several MKV clips that are arranged like this

Clips_folder
/spa/clip1.mka
/spa/clip2.mka
/ger/clip1.mka
/ger/clip2.mka
/clip1.mkv
/clip2.mkv

That's the script I have (based on 'Append argument to arguments list'):

#!/bin/zsh

mkdir -p output

for video in *.mkv
do
    audioargs=("-o ./output/${video} --language 0:eng ${video}")
    for audiodir in *(/)
        do
            audioargs+=("--language 0:${audiodir} ./${audiodir}/${video:r}.mka")
        done
    echo ${audioargs[@]}
done

That's the output:

-o ./output/clip1.mkv --language 0:eng clip1.mkv --language 0:spa ./spa/clip1.mka --language 0:ger ./ger/clip1.mka

But when I change it to mkvmerge ${audioargs[@]} I get

mkvmerge v45.0.0 ('Heaven in Pennies') 64-bit
Error: no destination file name was given

How do I correctly pass audioargs to mkvmerge so that it's expanded to mkvmerge -o file --language ... etc?

1 Answer 1

4

I don't have mkvmerge to test with, but I'm pretty sure the problem is how you quote things when you build the array. When you do something like

audioargs=("-o ./output/${video} --language 0:eng ${video}")

The double-quotes tell the shell to treat that whole thing as one long string, so it gets stored as a single element in the array, and therefore passed to mkvmerge as a single argument containing spaces, rather than a series of arguments.

Note that echo hides the distinction between a space within an argument and a space between arguments, making it highly misleading for things like this. Putting set -x before the command should clarify what's actually happening. With your example filenames, set -x shows what's being run:

echo '-o ./output/clip2.mkv --language 0:eng clip2.mkv' '--language 0:ger ./ger/clip2.mka' '--language 0:spa ./spa/clip2.mka'

See the long single-quoted sections? That's how it indicates those are long arguments containing spaces, rather than sequences of separate arguments.

To solve it, just use normal quoting when you build the array (i.e. the same quoting you'd use when passing arguments directly to the command). zsh doesn't word-split by default, so technically you don't need to quote at all, but I prefer to follow compatible-with-other-shells quoting style, so I quote all variable expansions:

#!/bin/zsh

mkdir -p output

for video in *.mkv
do
    audioargs=(-o "./output/${video}" --language 0:eng "./${video}")
    for audiodir in *(/)
        do
            audioargs+=(--language "0:${audiodir}" "./${audiodir}/${video:r}.mka")
        done
    echo "${audioargs[@]}"
done

Which gives this result with set -x:

echo -o ./output/clip2.mkv --language 0:eng ./clip2.mkv --language 0:ger ./ger/clip2.mka --language 0:spa ./spa/clip2.mka

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .