如何在BSD系统中使用xargs和find命令?

5

使用GNU find,将结果传递给xargs非常容易。以下是一个典型(无用)的示例:

find /var/log -name "*.log" | xargs dirname

这个命令会返回所有包含日志文件的目录名称。

使用BSD find 的相同命令不起作用,最终出现以下错误:

usage: dirname path

这是因为xargs无法将文件列表条目传递给dirname
BSD的find手册提到了-exec-execdir选项,指出“此行为类似于xargs(1)”。
引用块:

-exec utility [argument ...] {} + 与-exec相同,只是“{}”被尽可能多的路径替换以调用utility。此行为类似于xargs(1)。

-execdir utility [argument ...] {} + 与-execdir相同,只是“{}”被尽可能多的路径替换以调用utility。此行为类似于xargs(1)。

每次我回归这两个标志时,我都必须再次阅读文档。我似乎无法记住它们的用法!此外,我关注脚本在GNU / BSD系统之间的便携性,基本上是Linux,Open / FreeBSD和MacOS。
有没有办法将BSD的find管道传递到xargs,或者说-exec是唯一的选择?
1个回答

5

GNU和FreeBSD版本的xargs都支持通过-I标志将来自stdin的字符串作为命令的一部分传递给命令。你所需要做的就是

find /var/log -name "*.log" | xargs -I {} dirname -- "{}"

GNU xargs页面关于该标志的说明如下:

-I replace-str 将初始参数中出现的replace-str替换为从标准输入读取的名称。

这提供了一种与使用-exec-execdir不同的方式。然而,话虽如此,对于你的情况来说,使用-exec并不太复杂。
find /var/log -name "*.log" -type f -exec dirname "{}" \;

你知道为什么BSD的xargs会导致那个错误吗?我刚刚在将echo的输出导入到xargs dirname时遇到了这个问题。奇怪的是,使用args basename却可以正常工作。 - Noel Yap
进一步查看后,这并没有按预期工作。从 echo 输入的行被处理为一行。 - Noel Yap
@NoelYap 这个答案是基于原始问题的,如果你有不同的输入,请提出一个新问题,并说明哪些部分出了问题,以便得到帮助。 - Inian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接