Linux 获取超大文件系统上每个文件的文件大小
我必须将包含数百万个文件的20TB文件系统移动到ZFS文件系统。所以我想了解一下文件大小,以便选择好块大小 我目前的想法是`stat--format=“%s”每个文件,然后将这些文件分为多个文件箱Linux 获取超大文件系统上每个文件的文件大小,linux,bash,ubuntu,filesystems,centos,Linux,Bash,Ubuntu,Filesystems,Centos,我必须将包含数百万个文件的20TB文件系统移动到ZFS文件系统。所以我想了解一下文件大小,以便选择好块大小 我目前的想法是`stat--format=“%s”每个文件,然后将这些文件分为多个文件箱 #!/bin/bash A=0 # nr of files <= 2^10 B=0 # nr of files <= 2^11 C=0 # nr of files <= 2^12 D=0 # nr of files <= 2^13 E=0 # nr of files <
#!/bin/bash
A=0 # nr of files <= 2^10
B=0 # nr of files <= 2^11
C=0 # nr of files <= 2^12
D=0 # nr of files <= 2^13
E=0 # nr of files <= 2^14
F=0 # nr of files <= 2^15
G=0 # nr of files <= 2^16
H=0 # nr of files <= 2^17
I=0 # nr of files > 2^17
for f in $(find /bin -type f); do
SIZE=$(stat --format="%s" $f)
if [ $SIZE -le 1024 ]; then
let $A++
elif [ $SIZE -le 2048 ]; then
let $B++
elif [ $SIZE -le 4096 ]; then
let $C++
fi
done
echo $A
echo $B
echo $C
#/bin/bash
A=0个文件主要问题是使用命令替换将find
的输出提供给for
循环。命令替换通过在括号(或反勾号)内运行命令来完成,收集其输出,并将其替换到脚本中。这不支持流式传输,这意味着for循环在find
扫描完成之前不会运行,并且需要大量内存来缓冲find
的输出
特别是因为您正在扫描大量TB的文件,所以您需要使用支持流式传输的东西,例如while
循环:
find /bin -type f | while read f; do
...
done
使用可以流式传输的东西,您的脚本至少可以工作,但请记住,这种技术会强制您为找到的每个文件调用一次外部命令(stat
)。这将导致stat
命令的大量进程创建、销毁和启动成本。如果您有GNU find,例如,在find
命令中使用-printf
选项输出每个文件的大小的东西将执行得更好
旁白:让循环体中的
语句看起来是错误的。您正在扩展$A
、$B
和$C
变量的内容,而不是引用它们。你不应该在这里使用$
。如果你只想知道100M到1000M之间的文件数,你可以做以下操作
find . -size +100M -size -1000M -type f | wc -l
我将研究使用dd来读取zfs元数据,这些元数据应该包含在数据磁盘上
这可能是一个不好的建议,可能会导致你浪费时间。但是,使用bash对文件系统进行爬网将花费很长时间,并且会降低系统cpu利用率
find /bin/ -type f -printf "%s\n" > /tmp/a
然后将以下内容用作script.pl
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my %h = ();
while (<STDIN>) {
chomp;
if ($_ <= 2**10) { $h{1} += 1}
elsif ($_ <= 2**11) { $h{2} += 1}
elsif ($_ <= 2**12) { $h{4} += 1}
elsif ($_ <= 2**13) { $h{8} += 1}
elsif ($_ <= 2**14) { $h{16} += 1}
elsif ($_ <= 2**15) { $h{32} += 1}
elsif ($_ <= 2**16) { $h{64} += 1}
elsif ($_ <= 2**17) { $h{128} += 1}
elsif ($_ > 2**17) { $h{big} += 1}
}
print Dumper \%h;
#/usr/bin/perl
使用警告;
严格使用;
使用数据::转储程序;
我的%h=();
而(){
咀嚼;
如果($)\p>尊者会更直接地给你提供大小。也许可以使用awk
…但我一点也不相信你应该把大小相似的文件放在箱子里……你上面的代码有什么错误?@Mat它什么都没做。所以很难判断出什么错误。它似乎什么都没做(最终可能失败)。这只是因为你离磁盘太远,听不到它们的搅动声。这不是一个好的解决方案,因为我需要对每个范围的每个文件进行stat
。不能扩展到20TB。@SandraSchlichting实际上我认为这是一个非常好的替代解决方案。你必须使用不同的-size
参数运行此命令9次为了匹配9个bucket中的每一个,这意味着扫描文件系统9次,但每次扫描都比shell脚本快。如果我在echo$f
中执行find
命令,它不会打印任何内容。这就好像它不会像我一样进入循环。使用find/bin/-type f-printf%s\n">/tmp/all_size.txt
是一个非常有趣的想法,然后对输出进行后期处理。是的,您也可以使用管道将其流式处理,这样您就不需要将中间结果存储在一个非常大的临时文件中。很抱歉,不需要。如果您有时间研究此选项,那么我将阅读ZFS白皮书并进行设计然后开始实验。