
簡而言之,我想在命令中使用命令列出的目錄find
:
find $(produces_dir_names --options...) -find-options...
問題在於目錄名稱中存在空格。我認為在生成命令的輸出中引用它們(我可以更改)就足夠了:
"a" "a b" "a b c"
但 bash 抱怨道:
find: ‘"a"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b’: No such file or directory
find: ‘c"’: No such file or directory
如您所見, seebash
會在空格上分割指令的輸出,即使使用引號也是如此。我嘗試擺弄IFS
並將其設置為\n
,但我對它的理解似乎太有限,無法使其正常工作。
我發現的唯一解決方法是在這個 Stack Overflow 問題中:
bash指令取代刪除引號,即eval
在它前面放一個,但這看起來有點難看。
我的問題:
有沒有一種簡單的方法以及在沒有 的情況下編寫此替換會是什麼樣子eval
?
報價還有必要嗎?
範例(產生相同的輸出):
find $(echo '"a" "a b" "a b c"')
答案1
也許分兩行
IFS=$'\n' DIRS=( $(produces_dir_names --options...) )
find "${DIRS[@]}" -find-options...
例子:
$ mkdir -p "/tmp/test/a b/foo" "/tmp/test/x y/bar"
$ IFS=$'\n' DIRS=( $(printf "/tmp/test/a b\n/tmp/test/x y\n") )
$ find "${DIRS[@]}" -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar
但總的來說,這不是一個好的風格。例如,如果您的 DIRS 包含換行符,您就會遇到麻煩。更好地修復您的“ Produces_dir_names”以列印空字節終止的字串。關於我的例子,這將是這樣的:
$ printf "/tmp/test/a b\0/tmp/test/x y\0" | xargs -0 -I '{}' find '{}' -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar
如果您無法修復“products_dir_names”,則關於我的最後一條評論,最通用的解決方案將如下所示:
produces_dir_names --options... | tr '\n' '\0' | xargs -0 -I '{}' find '{}' -find-options...
除非您修復“ Produces_dir_names”以避免“換行符號”,否則“換行符號”仍然存在問題tr
。
答案2
魯迪邁爾的回答很好——具體來說,關於修改produces_dir_names
以打印空終止字串的部分——但從他的回答中可能並不明顯看出它find
為每個目錄執行一次。如果這足夠好,那就好了。但是,當然,可以使用find
多個起點進行呼叫;例如,
尋找 目錄1目錄2目錄3 -尋找選項...
從問題看來這就是你想要的。這可以如下完成:
printf "a\0a b\0a b c" | printf "a\0a b\0a b c" | xargs -0 sh -c '查找“$@”-尋找選項...' 什
這會導致xargs
呼叫sh -c
一次,並將所有目錄名稱附加到命令中。然後 shell 將會展開"$@"
為這些目錄名稱的清單。
PS 如果produces_dir_names
列出太多目錄名稱而無法放在一個命令列上,則將xargs
被迫產生一些命令。用於xargs --verbose
查看xargs
正在產生哪些命令。
答案3
只是為了揭開您收到的錯誤訊息的神秘面紗:
find: ‘"a"’: No such file or directory find: ‘"a’: No such file or directory find: ‘b"’: No such file or directory find: ‘"a’: No such file or directory find: ‘b’: No such file or directory find: ‘c"’: No such file or directory
答案是Bash 引號刪除不會刪除以下引號結果來自命令替換。
從LESS='+/^ *Quote Removal' man bash
Quote Removal After the preceding expansions, all unquoted occurrences of the charac- ters \, ', and " that did not result from one of the above expansions are removed.
引用的「前述擴展」包括:
EXPANSION Brace Expansion Tilde Expansion Parameter Expansion Command Substitution Arithmetic Expansion Process Substitution Word Splitting Pathname Expansion Quote Removal