Shell-Script
如何在 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
使其mkvmerge
擴展到mkvmerge -o file --language ...
等?
我不必
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 預設情況下不分詞,所以從技術上講你根本不需要引用,但我更喜歡遵循 compatible-with-other-shells 引用風格,所以我引用所有變數擴展:
#!/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