这个问题与这个问题非常相似:
事实上,我所有的尝试都在这个问题上列出。
不同之处在于我的列表有大量文件(1M+),而这些尝试似乎不适用于这么多条目。
对于stat
,du
我得到了这些错误:
-bash: /usr/bin/stat: Argument list too long
-bash: /usr/bin/du: Argument list too long
Perl 解决方案似乎可以工作,但速度非常慢,而且我不确定它是否可以处理完整列表或只是崩溃。
有没有任何解决方案不涉及将我的原始文件分成几部分,然后对部分总和进行求和?
答案1
要找出/some/dir/file
使用lstat()
或stat()
(如果您想解析符号链接)系统调用完成的文件的大小,系统需要:
- Lookup的 inode,检查您是否具有对其的读取和搜索访问权限,并获取有关目录内容所在位置的
/
信息:/
- 读取其中的内容
/
并查找some
其中的条目(获取其索引节点号)。 - 就像 for 一样
/
,查看/some
的 inode 以获得许可等。 - 重复 for
/some/dir
和 for/some/dir/file
/some/dir/file
检索的 inode中的大小属性
如果某些路径组件是符号链接,则也需要对其进行解析。
如果涉及 ACL 或其他安全上下文,这将使查找进一步复杂化。进行查找root
会绕过其中的一些部分并可能加快该过程。
因此,stat()
(或任何查找文件的系统调用)可能是一项成本高昂的操作,特别是如果所有数据(索引节点以及目录和安全属性的内容)没有缓存在内存中并且需要从计算机上的多个位置检索。硬盘。
即使该目录的内容已被缓存,在未索引的大型目录中查找文件的成本也可能相当高。
有用的方法是对文件列表进行排序,以便同一目录中的文件彼此相邻列出,并最大限度地提高在查找特定文件时缓存数据的机会。
您还需要避免运行太多命令,或者在上面做不必要的额外工作。
所以:
LC_ALL=C sort file | perl -lne '$s += -s} END {print $s'
(as root
) 可能接近您能够轻松达到的最快速度。
(这里使用stat()
系统调用,以便对于符号链接来说,要考虑它们指向的文件的大小)。
有一些方法可以进一步优化它。例如,如果您有:
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs/file1
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs/file2
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs/file3
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs/file4
open()
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs
一次然后相对于该目录执行一些fstatat()
for file1
, ...可能会更快,file2
以避免每次都必须查找所有这些 dir 组件,但实现这种优化并不是微不足道的(尽管不是那么简单)也很难)。
根据您的数据,也可以进行一些特定的优化。例如,如果一个文件被列出多次,您可以优化第二个和更多的stat()
s。如果/foo
是 的符号链接,并且下面列出了与 下/bar
相同的数千个文件,那么如果您可以意识到它们实际上是相同的文件,则可以优化一些s.与vs相同,.../foo
/bar
stat()
/foo/file
/foo/./file
/bar/../foo/file