您的位置:首页 > 其它

find -exec 与 find - xargs 的差别

2015-01-07 18:17 134 查看
最近我想统计下,家目录下各文件(夹)的硬盘占用情况,所以用了这个命令:
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 {} \;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: