Bash
為什麼 $() 不能正確展開?
我想使用 vlc 播放目錄中的所有 .mp3 文件,所以我執行以下操作:
vlc $(find ~/Documents/music -name "*.mp3" -exec "echo \"{}\"" \;)
問題是我得到“vlc:未知選項或缺少強制參數’-D’”。估計是解析問題。
所以讓我們逐個文件來做:
echo $(echo $(find ~/Documents/music -name "*.mp3" -exec echo "\"{}\" \n " \;) | head -n 1)
我得到:
"/home/XXX/Documents/music/My Folder/1 - track/the name of track.mp3"
當我執行時:
vlc "/home/XXX/Documents/music/My Folder/1 - track/the name of track.mp3"
有用。
但是當我跑步時
vlc $(echo $(find ~/Documents/music -name "*.mp3" -exec echo "\"{}\" \n " \;) | head -n 1)
我得到:
cannot open file /home/XXX/the (No such file or directory)
如果沒有正確引用 vlc 的參數,這將是有意義的。但他們是?那麼為什麼它被作為一個不帶引號的字元串傳遞給 vlc 呢?
引號不會在擴展的輸出中處理。如果你這樣做了
$(echo '"foo bar"')
,或者$(echo "\"foo bar\"")
,最後作為主命令的參數的是"foo
andbar"
。使用文字引號,並且由於分詞而作為兩個不同的參數。預設情況下,分詞發生在任何空格、空格或換行符上,因此從 的輸出中
find
,您無法區分哪個空格是文件名的一部分,以及哪個空格是find
分隔它們的列印內容的一部分。即使在一般情況下,您也無法區分它們,因為文件名也可以包含換行符……你可以做的是:
find ... -print0 | xargs -0 vlc
或者
find ... -exec vlc {} +
第一個
find
輸出了用 NUL 字節分隔的文件名,並告訴xargs
我們期待這一點。不過,並非所有系統都有find -print0
andxargs -0
。第二個
find
自己啟動vlc
,尾隨{} +
告訴它將多個文件名傳遞給vlc
.如果您要找到大量文件,並且它們不適合一個命令行,那麼這兩個文件可能會
vlc
多次啟動。看:
- Greg 的 wiki 上的分詞
- 問題為什麼我的 shell 腳本會因空格或其他特殊字元而窒息?,其中有很多相關的情況。
使用
echo
它來調試它並沒有真正起作用,因為它將用一個空格連接它的參數,從而無法區分echo foo bar
, 和echo "foo bar"
.