我目前的解决方案是find <expr> -exec printf '.' \; | wc -c,但是当结果超过10000时,这需要太长时间.有没有更快/更好的方法来做到这一点?
Bri*_*new 120
为什么不
find <expr> | wc -l
Run Code Online (Sandbox Code Playgroud)
作为简单的便携式解决方案 您的原始解决方案会为找到的每个文件生成一个新进程 printf,而且这非常昂贵(正如您刚刚发现的那样).
请注意,如果你有嵌入换行符的文件名,这将会超额计算,但如果你有,那么我怀疑你的问题运行得更深一些:-)
Gil*_*not 65
试试这个(需要find的-printf支持):
find <expr> -type f -printf '.' | wc -c
Run Code Online (Sandbox Code Playgroud)
它比计算线条更可靠,更快捷.
请注意,我使用的是find's printf,而不是外部命令.
让我们坐一会儿:
$ ls -1
a
e
l
ll.sh
r
t
y
z
Run Code Online (Sandbox Code Playgroud)
我的代码段基准:
$ time find -type f -printf '.' | wc -c
8
real 0m0.004s
user 0m0.000s
sys 0m0.007s
Run Code Online (Sandbox Code Playgroud)
全线:
$ time find -type f | wc -l
8
real 0m0.006s
user 0m0.003s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
所以我的解决方案更快=)(重要的部分是real线)
Qua*_*odo 10
符合 POSIX 标准且防换行:
find /path -exec printf %c {} + | wc -c
Run Code Online (Sandbox Code Playgroud)
而且,根据我在 中的测试/,它甚至不比其他解决方案慢两倍,这些解决方案要么不防换行,要么不可移植。
注意+代替\;. 这对于性能至关重要,因为每个文件名\;生成一个命令,而为单个命令提供尽可能多的文件名。(并且在可能存在太多参数的情况下,Find 会根据需要智能地生成新的 Printfs 来应对它,所以就好像printf+printf
{
printf %c very long argument list1
printf %c very long argument list2
printf %c very long argument list3
} | wc -c
Run Code Online (Sandbox Code Playgroud)
被称为。)
这个解决方案肯定比find -> wc这里的其他一些解决方案慢,但是如果除了计算文件名之外,您还倾向于对文件名做其他事情,您可以read从find输出中获取。
n=0
while read -r -d ''; do
((n++)) # count
# maybe perform another act on file
done < <(find <expr> -print0)
echo $n
Run Code Online (Sandbox Code Playgroud)
它只是对 BashGuide 中找到的解决方案的修改,该解决方案通过使用 将find输出定界符设为NUL 字节print0,并使用''(NUL 字节) 作为循环定界符从中读取来正确处理具有非标准名称的文件。
小智 5
这是我的countfiles函数~/.bashrc(它相当快,应该适用于 Linux 和 FreeBSD find,并且不会被包含换行符的文件路径所迷惑;最后wc只计算 NUL 字节):
countfiles ()
{
command find "${1:-.}" -type f -name "${2:-*}" -print0 |
command tr -dc '\0' | command wc -c;
return 0
}
countfiles
countfiles ~ '*.txt'
Run Code Online (Sandbox Code Playgroud)