題 find:-exec vs xargs(又名為什麼“find | xargs basename”會破壞?)


我試圖找到在子目錄中展開的某種類型的所有文件,為了我的目的,我只需要文件名。我嘗試通過剝離路徑組件 basename,但它不起作用 xargs

$ find . -name '*.deb' -print | xargs basename 
basename: extra operand `./pool/main/a/aalib/libaa1_1.4p5-37+b1_i386.deb'
Try `basename --help' for more information.

我得到同樣的事情(完全相同的錯誤)與這些變化之一:

$ find . -name '*.deb' -print0 | xargs -0 basename 
$ find . -name '*.deb' -print | xargs basename {}

另一方面,這可以按預期工作:

$ find . -name '*.deb' -exec basename {} \;
foo
bar
baz

這發生在最新的Cygwin和Debian 5.0.3上。我的診斷是xargs由於某種原因將兩條輸入行傳遞給basename,但為什麼呢?這裡發生了什麼?


10
2017-10-08 16:01


起源




答案:


因為 basename 只想要一個參數......不是很多。和 xargs 創造了很多參數。

要解決您的真實問題(僅列出文件名):

 find . -name '*.deb' -printf "%f\n"

其中只打印'basename'(man find):

 %f     File's name with any leading directories
        removed (only the last element).

22
2017-10-08 16:06



哦.... /再次拍打額頭/  我想我需要一本“尋找傻瓜”的書...... - quack quixote
我想到了 xargs 是它創建一個參數列表並將每個參數提供給後面的命令?否則它和之間的區別是什麼 find . -name '*.deb' | basename ? - WindowsMaker
GNU basename現在有一個 -a 選項:“支持多個參數並將每個參數視為名稱”。 - bishop
@WindowsMaker xargs 轉換 stdin 命令參數。在某種程度上,它是相反的 echo,將其參數轉換為 stdout。和...之間的不同 find ... | xargs -n1 basename 要么 find ... | xargs basename -a 和 find ... | basename 是前兩個將與實現 basename 那個無視 stdin。 - 8bittree


試試這個:

find . -name '*.deb' | xargs -n1 basename

17
2017-10-08 16:05



這不是解釋,這是一種解決方法。對於找到的任何文件,解決方法和通過-exec調用'basename'一樣好。 - akira
+1 ......雖然沒有解釋,但這會讓我調查你所展示的xargs開關,這最終會引導我前額拍打動作,我只是用來閱讀akira和john t的答案...... - quack quixote
我就是這樣做的。我不想學習所有的細節 find 命令,所以我只用它來查找和列出文件,我用xargs做其他一切。 - Ryan Thompson


basename只接受一個參數。運用 -exec 因為每個都正常工作 {} 由正在處理的當前文件名替換,命令運行一次 每個匹配的文件而不是試圖一次性將所有參數發送到basename。


4
2017-10-08 16:05





xargs 可以被迫只傳遞一個參數......

find . -name '*.deb' -print | xargs -n1 basename

這是有效的,但是接受的答案是使用 find 以更合適的方式。我發現這個問題正在尋找 xargs basename 因為我正在使用另一個命令來獲取文件位置列表。該 -n1 國旗 xargs 對我來說是最終的答案。


2
2017-07-10 23:18