有人能否确认下面的一行代码将生成 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
(和-0
)xargs
以避免出现潜在问题,例如文件名中的换行符,查看 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