为何find命令-exec选项中带输入重定向的wc命令无法生效?
为什么你的find命令无法正常工作?
老哥,你的命令失效的核心问题出在shell重定向的解析时机上,我给你掰扯明白:
问题根源
你想通过wc -c < 文件的方式让wc只输出字符数、不显示文件名——这个思路本身是对的:当wc从标准输入读取内容时,它只会输出统计数字,不会附带文件名。但把这个逻辑放到find -exec里就踩坑了,原因是:
find的-exec参数是直接把后续命令拆解成系统调用的参数,不会通过shell来解析重定向符号<。也就是说,你写的-exec wc -c < \{} \;,find会把<、替换后的文件名(比如/foo/bar.c)都当成wc的命令参数,而不是让shell把<理解成“从后面的文件读取内容”。- 这时候
wc会误以为<是一个要读取的文件名,自然找不到这个文件,要么报错,要么输出错误的统计结果。
正确的解决办法
要让重定向生效,必须让shell来解析<符号,所以得把命令包裹在shell里执行,有两种常用写法:
写法1:用sh -c执行单文件命令
find / -type f -name "*.c" -exec sh -c 'wc -c < "$1"' _ {} \;
这里的sh -c启动一个新shell,shell会解析<符号,把$1对应的文件作为标准输入传给wc,就能得到纯数字的字符数输出。_是占位符,用来填充shell的$0参数(不影响我们的逻辑)。
写法2:用cat管道替代重定向(效果一致)
如果你觉得重定向看着别扭,也可以用管道实现同样的效果:
find / -type f -name "*.c" -exec sh -c 'cat "$1" | wc -c' _ {} \;
额外小技巧
其实wc本身有个特性:当你给它传多个文件时,它会分别统计每个文件并带文件名,最后加总;但如果是从标准输入读,就只输出数字。所以本质上你要的就是让wc从标准输入读取每个单独的文件内容,上面两种写法都是围绕这个核心来实现的。
内容的提问来源于stack exchange,提问作者FilBr
相关产品推荐
相关产品推荐

