Xargs

xargs 如何處理 find 提供的文件名,這可能會導致問題?

  • June 9, 2018

來自 findutils 的手冊xargs

在許多應用程序中,如果 xargs 因文件名稱包含特殊字元而無法處理文件,則可能會失去一些數據。

但是,這裡是使用空格分隔的名稱可能導致的問題的一個極端範例。如果每天從 cron 執行以下命令,則任何使用者都可以刪除系統上的任何文件:

find / -name ’#*’ -atime +7 -print | xargs rm

例如,您可以執行以下操作:

eg$ echo > ’#
vmunix’

然後 cron將刪除 /vmunix,如果它以 / 作為目前目錄執行 xargs 。

刪除其他文件,例如 /u/joeuser/.plan,您可以這樣做:

eg$ mkdir ’#
’
eg$ cd ’#
’
eg$ mkdir u u/joeuser u/joeuser/.plan’
’
eg$ echo > u/joeuser/.plan’
/#foo’
eg$ cd ..
eg$ find . -name ’#*’ -print | xargs echo
./# ./# /u/joeuser/.plan /#foo

在上面的範例中,如何xargs處理由 提供的文件名find,以及如何刪除文件?

謝謝。

問題在於如何xargs讀取輸入並將其傳遞給命令。

我們可以很容易地看到這一點rm -i

$ touch a 'b c' 'd
> e'
$ find -type f | cat
./d
e
./b c
./a
$ find -type f | xargs rm -i
rm: cannot remove './d': No such file or directory
rm: cannot remove 'e': No such file or directory
rm: cannot remove './b': No such file or directory
rm: cannot remove 'c': No such file or directory
rm: remove regular empty file './a'? $ 

請注意,我們嘗試刪除 5 個文件;./a, ./b, c, ./d, 和e

因此,文件名中的空格和換行符都會導致將兩個參數傳遞給命令。

標準解決方案是使用find -print0xargs -0

$ find -type f -print0 | xargs -0 rm -i
rm: cannot remove '.': Is a directory
rm: remove regular empty file './d\ne'? 
rm: remove regular empty file './b c'? 
rm: remove regular empty file './a'? $ 

現在 NUL 字元(不能是文件名的一部分)用作分隔符,並且空格不重要。

引用自:https://unix.stackexchange.com/questions/448805