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

qua*_*ote 10 gnu command-line find xargs

我试图找到分布在子目录中的某种类型的所有文件,出于我的目的,我只需要文件名。我尝试通过 去除路径组件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.
Run Code Online (Sandbox Code Playgroud)

对于这些变体中的任何一个,我都得到了同样的东西(完全相同的错误):

$ find . -name '*.deb' -print0 | xargs -0 basename 
$ find . -name '*.deb' -print | xargs basename {}
Run Code Online (Sandbox Code Playgroud)

另一方面,这按预期工作:

$ find . -name '*.deb' -exec basename {} \;
foo
bar
baz
Run Code Online (Sandbox Code Playgroud)

这发生在最新的 Cygwin 和 Debian 5.0.3 上。我的诊断是 xargs 出于某种原因将两个输入行传递给 basename,但为什么呢?这里发生了什么?

aki*_*ira 24

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

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

 find . -name '*.deb' -printf "%f\n"
Run Code Online (Sandbox Code Playgroud)

只打印“基本名称”(man find):

 %f     File's name with any leading directories
        removed (only the last element).
Run Code Online (Sandbox Code Playgroud)


小智 20

尝试这个:

find . -name '*.deb' | xargs -n1 basename
Run Code Online (Sandbox Code Playgroud)

  • +1 ...虽然不是解释,但这会导致我调查您展示的 xargs 开关,这最终会导致我进行额头拍打动作,我只是在阅读 akira 和 john t 的回答时使用过... (4认同)