Как мне найти файлы и подсчитать их размеры?

12

Я хотел бы найти серию файлов (на основе подстановочного выражения) и общее их использование диска.

Что-то вроде этого:

$ find . -name 'flibble*' -ctime +90 -exec du -sh {} \;

2.1G    ./flibble_116.log
2.1G    ./flibble_83.log
2.1G    ./flibble_211040_157.log
2.1G    ./flibble3747_51.log

Эта работа. Но это не дает результата, который я ищу. В нем перечислены пространство, используемое каждым файлом, а также findитерация по ним.

То, что я хочу, это сумма duвсех найденных файлов.

Павел
источник

Ответы:

12

Решение

Предоставляя опцию -c(или --total) для du(1), вы можете дать ей указание произвести итоговую сумму. Если ваша реализация du(1)поддерживает один из этих параметров, вы можете добиться желаемого эффекта с помощью следующей команды:

$ find . -name 'flibble*' -ctime +90 -exec du -shc {} +

РЕДАКТИРОВАТЬ: обратите внимание, что если количество файлов превышает максимальное количество параметров, разрешенных вашей системой, findвсе равно может выполняться commandнесколько раз. Некоторые реализации du(1)также поддерживают чтение имен файлов из файла, который не страдает от упомянутого ограничения:

$ find -name 'flibble*' -ctime +90 -print0 > filenames
$ du -shc --files0-from=filenames

объяснение

Разница между семантикой -exec command {} \;и -exec command {} +заключается в следующем:

  • command {} \;выполняется commandодин раз для каждого результата find. Путь к результату передается вместо {}.

    $ touch 1 2 3
    $ find  1 2 3 -maxdepth 0 -exec echo {} \;
    1
    2
    3
  • command {} +выполняется command, когда все результаты были получены. Путь к результатам передается вместо {}.

    $ touch 1 2 3
    $ find  1 2 3 -maxdepth 0 -exec echo {} +
    1 2 3

-print0Опция заставляет find(1)печатать найденные имена файлов в стандартный вывод , разделенных нулевым символом, а --files0-fromопция вызывается du(1)для чтения нуль разделенных имен файлов. В отличие от символа новой строки, нулевой символ может не отображаться в имени файла, поэтому вывод является однозначным.

Чтобы узнать больше о возможностях du(1)и find(1), вам следует обратиться к соответствующим страницам справки:

$ man du
$ man find
Witiko
источник
2
Вы можете получить несколько итогов, если количество файлов важно (1K +) из-за ограничения количества аргументов командной строки.
10
Я могу подтвердить @ychaouche, у меня возникла проблема при попытке оценить размер более 30 тыс. Файлов.
Адриен Х
Если это проблема, некоторые реализации du(1)также поддерживают чтение имен файлов из файла find 1 2 3 -maxdepth 0 -print0 > filenames; du -shc --files0-from=filenames.
Witiko
4

Попробуй это:

du -c `find . -name 'flibble*' -ctime +90` | tail -1

Исходная команда дает du один аргумент, затем выполняет его, пока не пройдет все аргументы. Таким образом, вы просто приводите все аргументы сразу, затем обрезаете отдельные размеры и оставляете только общее количество. Вы можете удалить трубу и хвост, чтобы показать размер каждого файла, если хотите.

Андре С.
источник
Это не даст правильных результатов с путями, содержащими пробелы. Правильный способ сделать это - использовать -exec du -c {} +параметр find, который будет передавать пути без изменений du.
Witiko
4

Вы можете попробовать это:

find . -name 'flibble*' -ctime +90 -exec du -ch {} + | grep total
skush
источник
2

Я бы findсам распечатал размер и использовал другой инструмент для вычисления суммы:

find . -name 'flibble*' -ctime +90 -printf "%s\n" |
perl -lnE '$sum += $_} END {say $sum'

Если вы также хотите увидеть имена файлов:

find . -name 'flibble*' -ctime +90 -printf "%s\t%p\n" |
perl -apE '$sum += $F[0]} END {say $sum'
Гленн Джекман
источник
1

Один лайнер, который должен работать для получения общего гигабайта на большинстве систем:

echo "$(( ($(find . -name 'flibble*' -ctime +90 -type f -printf '%k+' )0)/1024/1024 )) GB"
Роберт Бойд
источник