查找:-exec vs xargs(又名“ find | xargs basename”为什么会中断?)


10

我试图找到散布在子目录中的所有特定类型的文件,而出于我的目的,我只需要文件名。我尝试通过剥离路径组件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,但是为什么呢?这里发生了什么?

Answers:


23

因为basename只需要一个参数,而不是很多。并xargs创建了很多参数。

要解决您的实际问题(仅列出文件名):

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

仅打印“ basename”(人工查找):

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

1
哦.... /再打额头/ 我认为我需要一本“找傻瓜”书...
嘎嘎吉x德09年

我认为重点xargs是它创建了一个参数列表并将每个参数提供给后面的命令?否则和有什么区别find . -name '*.deb' | basename
WindowsMaker

GNU basename现在具有一个-a选项:“支持多个参数并将每个参数都视为一个名称”。
主教

1
@WindowsMaker xargs转换stdin为命令参数。在某种程度上,它与的相反echo,它将其参数转换为stdout。之间的差异find ... | xargs -n1 basenamefind ... | xargs basename -afind ... | basename是前两种将与实现工作basename无视stdin
8bittree '12

19

尝试这个:

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

这不是解释,这是一种解决方法。解决方法就像通过-exec为找到的任何文件调用'basename'一样好。
akira

4
+1 ...虽然不是一种解释,但它会使我研究您显示的xargs开关,最终使我进入我刚刚阅读akira和john t的答案时所用的额头拍击动作
quack quixote

1
这就是我的方法。我不想学习find命令的所有内容,因此我仅将其用于查找和列出文件,而将xargs用于其他所有内容。
瑞安·汤普森

4

basename仅接受一个参数。使用-exec可以正常工作,因为每个{}都被当前正在处理的文件名替换,并且每个匹配的文件运行一次命令,而不是尝试一次将所有参数发送给basename。


3

xargs 也可能被迫只传递一个论点...

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

这是可行的,但是可接受的答案正在find以更适当的方式使用。我发现这个问题是在寻找xargs basename问题,因为我正在使用另一个命令来获取文件位置列表。对我来说,-n1标志xargs是最终的答案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.