Получить список, добавить размеры и отсортировать его по владельцу (с Perl)
perl -wE'
chdir (shift // ".");
for (glob ".* *") {
next if not -f;
($owner_id, $size) = (stat)[4,7]
or do { warn "Trouble stat for: $_"; next };
$rept{$owner_id} += $size
}
say (getpwuid($_)//$_, " => $rept{$_} bytes") for sort keys %rept
'
Я не смог сравниться с ним, и стоило бы попробовать его на подходегде каталог перебирается, в отличие от glob
-ed (хотя я обнаружил, что glob
гораздо быстрее в связанной с проблемой ).
Я ожидаю хорошего времени выполнения по сравнению с ls
, что значительно замедляет , поскольку список файлов в одном каталоге становится длинным.Это связано с системой, поэтому на Perl это тоже повлияет, но, насколько я помню, она справляется с этим гораздо лучше.Однако я наблюдал резкое замедление только после того, как число записей достигло полумиллиона или около того, а не нескольких тысяч, поэтому я не уверен, почему это работает медленно в вашей системе.
Если это необходимо сделать рекурсивным, тоиспользуйте File :: Find .Например,
perl -MFile::Find -wE'
$dir = shift // ".";
find( sub {
return if not -f;
($owner_id, $size) = (stat)[4,7]
or do { warn "Trouble stat for: $_"; return };
$rept{$owner_id} += $size
}, $dir );
say (getpwuid($_)//$_, "$_ => $rept{$_} bytes") for keys %rept
'
Это сканирует каталог с 2,4 ГБ, в основном небольшими файлами, по иерархии подкаталогов, за чуть более 2 секунд.du -sh
заняло около 5 секунд (первый раунд).
Разумно объединить эти два в один скрипт
use warnings;
use strict;
use feature 'say';
use File::Find;
use Getopt::Long;
my %rept;
sub get_sizes {
return if not -f;
my ($owner_id, $size) = (stat)[4,7]
or do { warn "Trouble stat for: $_"; return };
$rept{$owner_id} += $size
}
my ($dir, $recurse) = ('.', '');
GetOptions('recursive|r!' => \$recurse, 'directory|d=s' => \$dir)
or die "Usage: $0 [--recursive] [--directory dirname]\n";
($recurse)
? find( { wanted => \&get_sizes }, $dir )
: find( { wanted => \&get_sizes,
preprocess => sub { return grep { -f } @_ } }, $dir );
say (getpwuid($_)//$_, " => $rept{$_} bytes") for keys %rept;
Я считаю, что это работает примерно так же, как код с одним dir-кодом выше, при запуске безрекурсивно (по умолчанию в существующем виде).
Обратите внимание, что интерфейс File :: Find :: Rule имеет много удобств, но в некоторых важных случаях использования медленнее , что явноимеет значение здесь(Этот анализ должен быть переделан, так как ему несколько лет.)