を使用してmkvmerge
、このように配置された複数のMKVクリップにオーディオトラックを追加したい
Clips_folder
/spa/clip1.mka
/spa/clip2.mka
/ger/clip1.mka
/ger/clip2.mka
/clip1.mkv
/clip2.mkv
これが私が持っているスクリプトです(「引数リストに引数を追加」に基づく):
#!/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
出力は次のようになります:
-o ./output/clip1.mkv --language 0:eng clip1.mkv --language 0:spa ./spa/clip1.mka --language 0:ger ./ger/clip1.mka
しかし、これを変更してみるmkvmerge ${audioargs[@]}
と
mkvmerge v45.0.0 ('Heaven in Pennies') 64-bit
Error: no destination file name was given
などに展開されるように正しく渡すaudioargs
にはどうすればよいですか?mkvmerge
mkvmerge -o file --language ...
答え1
テストする必要はありませんmkvmerge
が、配列を構築するときに引用符をどのように付けるかが問題だと確信しています。次のようなことをすると
audioargs=("-o ./output/${video} --language 0:eng ${video}")
二重引用符は、全体を 1 つの長い文字列として扱うようにシェルに指示します。そのため、配列内の 1 つの要素として格納され、mkvmerge
一連の引数ではなく、スペースを含む単一の引数として渡されます。
echo
引数内のスペースと引数外のスペースの区別が隠れていることに注意してください。間引数が多すぎるため、このような場合に非常に誤解を招きます。set -x
コマンドの前に置くと、実際に何が起こっているかが明確になります。例のファイル名では、set -x
何が実行されているかを示します。
echo '-o ./output/clip2.mkv --language 0:eng clip2.mkv' '--language 0:ger ./ger/clip2.mka' '--language 0:spa ./spa/clip2.mka'
長い一重引用符で囲まれたセクションが見えますか? これは、これらが個別の引数のシーケンスではなく、スペースを含む長い引数であることを示しています。
これを解決するには、配列を構築するときに通常の引用符を使用します (つまり、引数をコマンドに直接渡すときに使用するのと同じ引用符)。zsh はデフォルトでは単語を分割しないので、技術的にはまったく引用符を使用する必要はありませんが、私は他のシェルと互換性のある引用符スタイルに従うことを好むため、すべての変数展開を引用符で囲みます。
#!/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
これにより、次の結果が得られますset -x
。
echo -o ./output/clip2.mkv --language 0:eng ./clip2.mkv --language 0:ger ./ger/clip2.mka --language 0:spa ./spa/clip2.mka