bash – 什么是计算查找结果的最佳方法?

我现在的解决scheme是find <expr> -exec printf '.' \; | wc -c find <expr> -exec printf '.' \; | wc -c find <expr> -exec printf '.' \; | wc -c ,但是当结果超过10000时,这需要太长的时间。 有没有更快/更好的方法来做到这一点?

为什么不

 find <expr> | wc -l 

作为简单的便携式解决scheme 您的原始解决scheme是为每个find的单个文件生成一个新的进程 printf ,而且这非常昂贵(正如您刚发现的那样)。

请注意,如果你有embedded换行符的文件名,这将会计数过多,但是如果你有这个,那么我怀疑你的问题会变得更深一些:-)

试试这个(需要find-printf支持):

 find <expr> -type f -printf '.' | wc -c 

这将比计数线路更可靠和更快。

请注意,我使用findprintf ,而不是外部命令。


让我们来看一下:

 $ ls -1 a e l ll.sh r t y z 

我的片段基准:

 $ time find -type f -printf '.' | wc -c 8 real 0m0.004s user 0m0.000s sys 0m0.007s 

全线:

 $ time find -type f | wc -l 8 real 0m0.006s user 0m0.003s sys 0m0.000s 

所以我的解决scheme更快=)(重要的部分是real线)

这是我的~/.bashrc countfiles函数(它速度相当快,应该适用于Linux和FreeBSD的find ,并且不会被包含换行符的文件path所迷惑;最后的wc只计算NUL字节):

 countfiles () { command find "${1:-.}" -type f -name "${2:-*}" -print0 | command tr -dc '\0' | command wc -c; return 0 } countfiles countfiles ~ '*.txt' 

这个解决scheme肯定比其他一些find -> wc解决scheme要慢一些,但是如果你想用文件名做别的事情,除了计算它们之外,你可以从find输出中read

 n=0 while read -r -d ''; do ((n++)) # count # maybe perform another act on file done < <(find <expr> -print0) echo $n 

这只是对BashGuide中find的解决scheme的修改,通过使用print0使find输出分隔符成为NUL字节,并使用'' (NUL字节)作为循环分隔符来读取它,从而正确处理非标准名称的文件。

当我偶然发现一个速度比赛时我喜欢。 使用wc没什么问题,但只要我们是基准testing – 这里是(我认为)最便携和最快的解决scheme:“

 $ time (i=0; for d in /dev/sd*[az]; do ((i++)); done; echo $i) 25 real 0m0.001s user 0m0.000s sys 0m0.000s 

与使用find / wc相比:

 $ time find /dev/sd*[az] | wc -l 25 real 0m0.006s user 0m0.000s sys 0m0.004s $ time find /dev/sd*[az] -printf . | wc -c 25 real 0m0.005s user 0m0.000s sys 0m0.000s 

请注意,如果您需要考虑隐藏文件,则for循环中必须包含2个参数: for devfile in /dev/.* /dev/*; do ... for devfile in /dev/.* /dev/*; do ...而且它保持快捷。

快乐的黑客!