ZSHループにパラメータを追加してコマンドに渡すにはどうすればよいですか?

ZSHループにパラメータを追加してコマンドに渡すにはどうすればよいですか?

を使用して、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配信するにはどうすればよいですか?mkvmergemkvmerge -o file --language ...

答え1

テストする必要はありませんでしたが、mkvmerge配列を構築するときにコンテンツを参照する方法に問題があることは確かです。何かをするとき

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

二重引用符は、内容全体を単一の長い文字列として処理するようにシェルに指示するため、配列に単一の要素として格納されるため、一連の引数ではなく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

関連情報