如何递归地为深层目录结构中的每个文件执行命令?

UpT*_*eek 7 linux bash

我有一个很深的目录结构,有大量的文件(大约 1M)。我想对每个执行命令。(在我的情况下,文件是我想针对它运行 optipng 的 png。)

我试过这个:

find . -name *.png | xargs sudo optipng -o2
Run Code Online (Sandbox Code Playgroud)

但我收到错误argument list too long

我假设 xargs 应该能够处理这个问题,而且我的语法一定有问题。

Ger*_*nes 7

直接使用 find 而不是通过 xargs 执行 exec。

sudo find . -name '*.png' -exec optipng -o {} +
Run Code Online (Sandbox Code Playgroud)

  • 是的,`find` 以 root 身份运行,它产生 `optipng`,因为它由 root 拥有的进程产生,也将作为 root 运行。 (2认同)

Sve*_*ven 4

如您所见,使用 sudo 作为执行命令xargs不起作用。换个方式试试:

find . -name '*.png' | sudo xargs optipng -o2
Run Code Online (Sandbox Code Playgroud)

不同之处在于您的版本创建了一个类似的命令

 sudo optipng -o2 file1 file2 file3 file4 ......
Run Code Online (Sandbox Code Playgroud)

而 sudo 无法处理这么多参数。

相反,执行 sudo 一次,然后启动,xargs然后生成如下命令

optipng -o2 file1 file2 file3 file4 ......
Run Code Online (Sandbox Code Playgroud)

如果optipng可以处理许多文件作为参数,它应该可以工作。

如果这仍然不起作用,您将不得不-exec像杰兰特的答案那样使用,但这应该是您的最后手段。

  • 如果 `-exec` 命令以 `+` 而不是 `;` 终止,则 find 会将文件分组到足够小的组中,以避免出现“参数列表太长”错误。(您还必须在“+”之前提供一个“{}”参数,该参数将被文件名列表替换。)此功能不在原始的 unix“find”中,但它已经存在了足够长的时间(在 POSIX 中已经超过了10 年)...是时候忘掉 `xargs` 的使用了。 (6认同)
  • @GeraintJones:不,因为这正是“xargs”的工作来确保这种情况不会发生。 (4认同)
  • 他说 1M 文件,bash 说的是“参数列表太长”而不是“optipng”或“sudo”。如果你确实有 100 万个文件,你唯一的选择就是使用 `-exec` (2认同)