最近我想统计下,家目录下各文件(夹)的硬盘占用情况,所以用了这个命令:find -maxdepth 1 | xargs du -sh
返回的结果是,整个家目录的总大小,而不是预期的每个文件的大小。之后换用了find -maxdepth 1 -exec du -sh {} \;
就能得出每个文件的大小。
为什么使用find | xargs
得出的结果跟find -exec
不一样呢?
一个问题是,我们为什么要使用xargs?xargs对find的标准输出做了什么处理?
以下面为例:
[lzx:~/.oh-my-zsh]¥ find -maxdepth 1 | xargs
. ./plugins ./templates ./.git ./README.textile ./oh-my-zsh.sh ./log ./.gitignore ./custom ./cache ./MIT-LICENSE.txt ./themes ./tools ./lib
[lzx:~/.oh-my-zsh]¥ find -maxdepth 1
.
./plugins
./templates
./.git
./README.textile
./oh-my-zsh.sh
./log
./.gitignore
./custom
./cache
./MIT-LICENSE.txt
./themes
./tools
./lib
默认情况下,xargs只是把\n转换成了空格。
所以find -maxdepth 1 | xargs du -sh
近似于:du -sh . ./plugins ./templates ./.git ./README.textile ./oh-my-zsh.sh ./log ./.gitignore ./custom ./cache ./MIT-LICENSE.txt ./themes ./tools ./lib
结果是6.8M,而不是独立计算每个文件夹的硬盘占用。
有趣的是,如果移除所有条目前面的./
,得出的结果就是
du -s cache custom lib log MIT-LICENSE.txt oh-my-zsh.sh plugins README.textile templates themes tools .git .
924K cache
20K custom
72K lib
8.0K log
4.0K MIT-LICENSE.txt
4.0K oh-my-zsh.sh
2.0M plugins
8.0K README.textile
8.0K templates
572K themes
32K tools
3.2M .git
8.0K .
可见,使用find | xargs
和find -exec
之所以会得出不同的结果,du对命令行输入的处理方式也是原因之一。
再来看下find -exec
是怎样的:
这里写了个argv.rb脚本,简单地输出命令行参数。
[lzx:~]¥ find ./code -exec ./argv.rb {} \;
["./code"]
["./code/test"]
["./code/test/package.json"]
["./code/test/public"]
["./code/test/public/javascripts"]
["./code/test/public/images"]
["./code/test/public/stylesheets"]
["./code/test/public/stylesheets/style.styl"]
["./code/test/public/stylesheets/style.css"]
["./code/test/views"]
["./code/test/views/user.ejs"]
["./code/test/views/index.ejs"]
["./code/test/views/error.ejs"]
["./code/test/models"]
["./code/test/models/User.js"]
...
[lzx:~]¥ find ./code | xargs ./argv.rb
["./code", "./code/test", "./code/test/package.json", "./code/test/public", "./code/test/public/javascripts", "./code/test/public/images", "./code/test/public/stylesheets", "./code/test/public/stylesheets/style.styl", "./code/test/public/stylesheets/style.css", "./code/test/views", "./code/test/views/user.ejs", "./code/test/views/index.ejs", "./code/test/views/error.ejs", "./code/test/models", "./code/test/models/User.js", ...]
可见find -exec
是对每一个匹配的文件都执行了命令。
不过,如果不是以{} \;
结尾({}
会被替换成匹配的文件名),而是以{} +
结尾,那么命令只会在最后执行一次。这类似于使用xargs
的结果。
BTW,既然xargs只是简单地把\n变成空格,那么可能存在一些问题。比如文件名带空格,这时候xargs就给跪了。万一空格之后是-xx
那样的内容,那就有得看了。当然通过指定\0作为分隔符,可以避免这种情况:
find . -maxdepth 1 -print0 | xargs -0 xxx
但是这么麻烦,还是坚持使用find . -exec xxx {} \;
好了。
后记: 经别人指正,其实使用du -hd 1
就能统计当前目录下各个文件(夹)占用的大小,无需使用find -maxdepth 1 -exec du -sh {} \;
。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。