find 和 du 计算总大小 vs xargs

find 和 du 计算总大小 vs xargs

有人能否确认下面的一行代码将生成 FIND 找到的所有名称中包含 log 的目录的总可读大小?

find -type d -name *log* | du -hcs

答案1

准备好?

find . -type d -name '*log*' -print0 | xargs -0 du -hcs

  • 用单引号引起来*log*,否则 shell 会在find看到它之前将其展开。
  • 用于-print0通过空字符分隔查找输出xargs
  • 用于xargs -0将每个以空字符分隔的文件名放入find命令行中du

很简单,对吧?:)

答案2

您的一行代码有两个主要问题:

  • 该命令find | du将 的输出传递find给 的标准输入du。但是,du完全忽略标准输入,因此find过滤器被完全忽略,您提供的命令实际上相当于du -hcs。解决方案是使用xargs,它将文件列表作为参数传递给du、 或du --files0-from=-(GNU coreutils)。
  • 你需要引用文件名模式中的星号必须用反斜杠 ( \*log\*) 或单引号 ( '*log*') 括起来,否则 shell 将尝试执行文件名扩展并且find可能根本看不到星号。

更多改进:

  • 如果在匹配的目录中有匹配项,例如./log/log/,则./log/和都./log/log/将传递给du。第二个目录将被忽略du -s,但您可以find通过添加-prune操作来提高命令的性能。它将确保find不会进一步深入到匹配的目录中。
  • 我添加了-print0(和-0xargs以避免出现潜在问题,例如文件名中的换行符,查看 serverfault
  • 我正在添加路径(.)以使find命令与 POSIX(和 BSD)兼容。

这是最后一句:

find . -type d -name '*log*' -prune -print0 | xargs -0 du -hcs

请记住-name区分大小写。我个人几乎总是使用-iname不区分大小写的。


附加说明:如果您使用 GNU coreutils du,您可以使用其--files0-from=-选项并将文件路径直接传递给du,省略xargs。根据手动的, “当文件名列表太长以至于可能超出命令行长度限制时,这很有用。”

find . -type d -name '*log*' -print0 | du --files0-from=- -hcs

相关内容