![有没有比 `find . | wc -l` 更快的方法来计算目录中的文件数量?](https://linux22.com/image/1389993/%E6%9C%89%E6%B2%A1%E6%9C%89%E6%AF%94%20%60find%20.%20%7C%20wc%20-l%60%20%E6%9B%B4%E5%BF%AB%E7%9A%84%E6%96%B9%E6%B3%95%E6%9D%A5%E8%AE%A1%E7%AE%97%E7%9B%AE%E5%BD%95%E4%B8%AD%E7%9A%84%E6%96%87%E4%BB%B6%E6%95%B0%E9%87%8F%EF%BC%9F.png)
我经常需要计算某个目录中文件的数量,有时候这个数字会达到数百万。
除了枚举和计数之外,还有更好的方法吗find . | wc -l
? 是否有某种可以在 ext3/4 上进行 I/O 密集程度较低的文件系统调用?
答案1
虽然不是根本性的加速,但至少有一点:)
find . -printf \\n | wc -l
您实际上不需要传递文件名列表,只需传递换行符即可。当目录缓存在 RAM 中时,此变体在我的 Ubuntu 12.04.3 上的速度提高了约 15%。此外,此变体可以正确处理包含换行符的文件名。
有趣的是,这个变体似乎比上面的变体慢一点:
find . -printf x | wc -c
特殊情况 - 但速度非常快
如果目录位于其自己的文件系统上,您可以简单地计算 inode:
df -i .
如果除已计数的目录之外的其他目录中的目录和文件数量没有太大变化,您可以简单地从当前df -i
结果中减去这个已知数字。这样,您将能够非常快速地计算文件和目录的数量。
答案2
我已经写了毛细管气管正是出于这个目的。它使用 ioctl 检索目录本身的物理偏移量fiemap
,然后将目录遍历安排在多个连续的传递中以减少随机访问。与相比,您是否真正获得了加速取决于find | wc
以下几个因素:
- 文件系统类型:支持 ioctl 的文件系统(如 ext4)
fiemap
将受益最多 - 随机访问速度:HDD 的优势远大于 SSD
- 目录布局:嵌套目录数量越多,优化潜力越大
当访问会导致元数据更新时,使用relatime
或甚至重新安装也可能提高速度(对于所有方法)。nodiratime
答案3
实际上,在我的系统(Arch Linux)上,这个命令
ls -A | wc -l
比以上所有方法都快:
$ time find . | wc -l
1893
real 0m0.027s
user 0m0.004s
sys 0m0.004s
$ time find . -printf \\n | wc -l
1893
real 0m0.009s
user 0m0.000s
sys 0m0.008s
$ time find . -printf x | wc -c
1893
real 0m0.009s
user 0m0.000s
sys 0m0.008s
$ time ls -A | wc -l
1892
real 0m0.007s
user 0m0.000s
sys 0m0.004s
答案4
改用fd
find
. 这是并行遍历文件夹的快速替代方案
$时间查找〜-type f 2> / dev / null | wc -l 445705 find ~ -type f 2> /dev/null 0.84s 用户 13.57s 系统 51% cpu总计 28.075 wc -l 0.03s 用户 0.02s 系统 0% cpu总计 28.074 $时间 fd -tf -sHI --显示错误。〜2> / dev / null | wc -l 445705 fd -tf -sHI --show-errors . ~ 2> /dev/null 2.66s 用户 14.81s 系统 628% cpu总计 2.780 wc -l 0.05s 用户 0.05s 系统 3% cpu总计 2.779
find
如您所见,要匹配中的选项,fd
您需要-sHI --show-errors
。默认情况下fd
会跳过隐藏文件/文件夹,.gitignore
并且也不会打印出权限错误,因此它甚至比这还要快得多。
可以通过仅打印新行而不是管道传输整个路径来进一步调整这一点。find
您可以使用 来实现这一点-printf '\n'
。目前不支持此功能fd
,但这是请求的功能
请注意,在 Ubuntu 中,由于名称冲突,您需要使用fdfind
而不是fd
。您可以alias fd=fdfind
克服较长的名称。显然,上述命令不适用于包含 的文件名\n
。您需要像这样修复它
fd -t f -sHI . ~ | tr '\0\n' '\n\0' | wc -l
另一个好处是fd
,当在交互式终端中运行它时,您还会获得漂亮的彩色文本,这与的输出不同find
。