Linux 获取超大文件系统上每个文件的文件大小

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 <

我必须将包含数百万个文件的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 <= 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白皮书并进行设计然后开始实验。