如何在 BSD find 中使用 xargs?

Eri*_*ton 5 shell portability bsd find xargs

有了 GNU find,就可以很容易地通过管道传输xargs。一个典型的(无用的)例子:

find /var/log -name "*.log" | xargs dirname
Run Code Online (Sandbox Code Playgroud)

这将返回包含某个日志文件的所有目录名称。

同样的命令在 BSD 中find不起作用,结尾为:

usage: dirname path
Run Code Online (Sandbox Code Playgroud)

xargs无法将文件列表条目传递给dirname.

BSDfind的联机帮助页提到了-exec-execdir选项,指出“此行为类似于 xargs(1)”。

-exec utility [argument ...] {} + 与 -exec 相同,但每次调用实用程序时,将“{}”替换为尽可能多的路径名。此行为与 xargs(1) 类似。

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

每次我依靠这两个标志时,我都必须再次阅读文档。我似乎记不起它们的用法了!另外,我还关心 GNU/BSD 系统(主要是 Linux、Open/FreeBSD 和 MacOS)之间的脚本可移植性。

有什么方法可以将 BSD 传输findxargs,或者-exec确实是唯一的选择?

Ini*_*ian 5

GNU 和 FreeBSD 版本都xargs支持将字符串作为标志的一部分从 stdin 传递到命令的方法-I。你需要做的就是

find /var/log -name "*.log" | xargs -I {} dirname -- "{}"
Run Code Online (Sandbox Code Playgroud)

GNUxargs页面关于该标志的描述为

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

-exec这提供了除使用or之外的另一种方法-execdir。然而,话虽如此,对于您的情况来说,使用-exec并不太复杂。

find /var/log -name "*.log" -type f -exec dirname "{}" \;
Run Code Online (Sandbox Code Playgroud)