* 和管道的区别

Yve*_*ves 0 pipe

说我想检查某个目录中每个文件的大小。

这是我所做的:

du -sh *
Run Code Online (Sandbox Code Playgroud)

另外,我可以这样做:

ls | xargs du -sh
Run Code Online (Sandbox Code Playgroud)

这两个命令做的事情完全一样。

我想知道它们是否完全相同,例如它们的成本、效率等。(我猜第一个命令比第二个命令轻?)

Ste*_*itt 11

一个是正​​确的,另一个是不正确的。

du -sh *
Run Code Online (Sandbox Code Playgroud)

(应该是du -sh -- *为了避免文件名以 开头的问题-

依靠 shell 来扩展 glob *du将当前目录中的所有非隐藏文件和目录视为单独的参数。这可以正确处理特殊字符。

ls | xargs du -sh
Run Code Online (Sandbox Code Playgroud)

依赖于xargs处理ls的输出。xargs将其输入拆分为空格(至少是空格、制表符和换行符,在某些实现中更多),还理解某种形式的引用,并du使用每个空格分隔的字符串运行(一次(即使是空输入¹)或多次调用)作为个别论点。

如果您的当前目录不包含名称中包含空格、单引号、双引号或反斜杠字符的文件,并且如果只有很少的文件(但至少有一个)xargs只运行一次du调用,则两者看起来是等效的,但它们是不是。

在效率方面,du -sh *使用一个过程,ls | xargs du -sh至少使用三个。在一种情况下,管道方法会起作用,而 glob 不会:如果当前目录中有太多文件,shell 将无法du一次性运行所有文件名,但xargs会运行du为需要多次覆盖所有文件,在这种情况下,您会看到多行,并且可能会多次计算具有多个硬链接的文件。

另见为什么*不*解析`ls`?


¹ 如果当前目录中没有非隐藏文件,则du -sh -- *您的 shell 会因错误而失败,或者某些 shellbashdu以文字*作为参数运行,并且du会抱怨该*文件不存在。

而 with ls | xargs du -sh --,大多数xargs实现(一些 BSD 除外)将在du没有参数的情况下运行,因此给出当前目录的磁盘使用情况(因此还包括目录文件本身的磁盘使用情况以及其中的所有隐藏文件和目录)