如何告訴xargs
忽略空標準輸出?
如何更改此程式碼以免發出錯誤,換句話說,
xargs
如果 stdout 為空,則不執行程式碼。終端:
$ cat << EOF > dummy.sh #! /usr/bin/env bash [[ -f "\$1" ]] && echo "file=\$1" || { echo "error"; exit 1; } shift (( \$# == 0 )) || "\$0" "\$@" EOF $ chmod +x dummy.sh $ mkdir trash.later && touch trash.later/foo $ find trash.later -type f | xargs -n 1 ./dummy.sh file=trash.later/foo $ find trash.later -type f | grep 'bar' | xargs -n 1 ./dummy.sh error
不要
xargs
在find
.xargs
預設情況下,期望輸入的參數以沒有命令輸出的格式分隔,當然不是find
. 的輸出find -print
也不能可靠地進行後處理。
find
使用xargs
可靠排序的唯一方法是使用-print0
和-0
非標準擴展(最初來自 GNUfind
/xargs
,但現在在許多其他實現中都可以找到)。如果輸入為空,GNU
xargs
也有一個-r
/副檔名來不執行命令(某些實現,例如 NetBSD 上的預設實現)。--no-run-if-empty``xargs
所以在這裡,使用 GNU
find
//xargs
或grep
兼容的,你可以這樣做:find trash.later -type f -print0 | grep -z bar | xargs -r -0 -n 1 ./dummy.sh
但這與標準相比沒有優勢:
find trash.later -path '*bar*' -type f -exec ./dummy.sh {} ';'
( where在文件路徑中
-path '*bar*'
查找任何地方,就像您嘗試做的那樣。替換為僅在文件名中查找(其路徑的最後一個組成部分))。bar``grep bar``-name '*bar*'``bar
作為對您問題的更一般的回答,對於
xargs
不支持-r
/的實現,--no-run-if-empty
解決方法是使用sh
包裝器。代替:
... | xargs -n1 cmd
做:
... | xargs sh -c 'for file do cmd "$file"; done' sh
sh
如果沒有輸入,它仍然會執行,但由於參數列表是空的,循環中不會有通過,所以cmd
不會執行。另請參閱僅在輸入非空時執行命令的
ifne
命令moreutils
... | ifne xargs -n1 cmd
但是請注意,如果輸入不為空但僅包含空行,
ifne
則將執行xargs
但xargs
仍會認為其輸入沒有參數並且仍然在cmd
沒有參數的情況下執行一次(NetBSD 除外)。為了完整性
... | xargs -I {} cmd {}
cmd
如果輸入為空/空白,也不會執行。在這種情況下,將輸入拆分為參數是不同的:前導空格被刪除,引號仍然被處理(以xargs
自己獨特的方式),但否則參數是整行而不是空格分隔的單詞。