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

查找:-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,但为什么呢?这是怎么回事?

答案1

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

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

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

仅打印“basename”(man find):

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

答案2

尝试这个:

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

答案3

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

答案4

原因是默认情况下xargs不会仅使用一个输入项来构建一个命令调用。

事实上,xargs每次执行命令时,都会使用尽可能多的输入项,其中构建一次命令调用所使用的最大项数是系统定义的值,可以通过-n-L选项覆盖。例如,如果您运行echo a b | xargs ls,而不是分别使用和执行ls两次,则会构建并运行单个命令。abxargsls a b

因此,对于仅接受一个参数的命令(如),如果您想坚持使用,则basename应该使用-n或选项。-Lxargs

相关内容