如何在 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

我如何正確地傳遞audioargsmkvmerge以便它擴展到mkvmerge -o file --language ...等?

答案1

我不必mkvmerge進行測試,但我很確定問題在於建立數組時如何引用內容。當你做類似的事情時

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

雙引號告訴 shell 將整個事物視為一個長字串,因此它作為單一元素儲存在陣列中,並因此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 預設不會進行分詞,因此從技術上講,您根本不需要引用,但我更喜歡遵循與其他 shell 相容的引用風格,因此我引用了所有變數擴展:

#!/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

相關內容