Найдите общий размер определенных файлов в рамках ответвления каталога

Для простых случаев существуют простые решения, поэтому если у Вас, оказывается, есть чистые, простые, базовые слова, без.? + * {} () [] \/и возможно более необычный sed-материал, можно передать список пар к sed-командному-файлу с sed:

sed -re 's,(^\\| \\|$),/,g;s/^/s/;s/$/g/' pairs.txt > pairs.sed
sed -f pairs.sed input > output
152
25.06.2012, 07:38
12 ответов
find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$

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

202
27.01.2020, 19:28
  • 1
    находит-iname 'файлом*' - должностное лицо du-cb {} + | grep total$ | сократило-f1 |, вставляют-sd + - | до н.э # суммированный размер –  Michal Čizmazia 15.07.2015, 16:55
  • 2
    Если Ваша система работает под другим языком затем, необходимо изменить total$ на другое слово как razem$ на польском языке. –  Zbyszek 26.07.2015, 15:49
  • 3
    Можно добавить LC_ALL=POSIX как префикс к всегда grep для общего количества как это: LC_ALL=POSIX find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$ –  Sven 27.06.2016, 08:48
  • 4
    Если Вы не используете -name, затем измените grep на grep -P "\ttotal$" или иначе это получит все файлы, заканчивающиеся "общим количеством" также. –  thdoan 30.03.2017, 10:43
  • 5
    @MichalČizmazia некоторые оболочки (например, Bash Мерзавца для Windows) не идут bc, таким образом, вот более портативное решение: find -name '*.jpg' -type f -exec du -bc {} + | grep total$ | cut -f1 | awk '{ total += $1 }; END { print total }' –  thdoan 30.03.2017, 10:55
du -ch public_html/images/*.jpg | grep total
20M total

дает мне общее использование моего .jpg файлы в этом каталоге.

Для контакта с несколькими каталогами, необходимо было бы, вероятно, объединить это с find так или иначе.

Вы могли бы найти примеры команды du полезными (это также включает find)

55
27.01.2020, 19:28
  • 1
    Это не пересекает базовые каталоги? –  mbaitoff 26.06.2012, 08:48

Прежде всего, Вам нужны две вещи:

du -ch -- **/*.jpg | tail -n 1
24
27.01.2020, 19:28
  • 1
    очень хороший ответ. Более простой, чем использование находят (поскольку долго * или ** соответствует структуре каталогов), –  Andre de Miranda 21.04.2016, 08:13
  • 2
    Это может также обработать очень длинные списки файлов тогда как использование find может возвратить ошибочные результаты. –  Eric Fournie 19.10.2016, 11:50

Ответы, которые были даны до сих пор, не учитывают, что список файлов, переданный из find в du, может быть настолько длинным, что поиск автоматически разбивает список на куски, в результате чего происходит многократное повторение всего .

Вы можете либо grep total (локаль!) и подвести итог вручную, либо использовать другую команду. AFAIK есть только два способа получить общую сумму (в килобайтах) всех найденных файлов:
find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=$1} END {print sum}'

Explanation
find . -тип f - имя '*.jpg' -print0: Найдите все файлы с расширением jpg вне зависимости от регистра (т.е. *.jpg, *.JPG, *.Jpg...) и выведите их (нуль-терминированные).
xargs -r0 du -a: -r: Xargs вызовет команду даже без аргументов, что предотвращает -r. -0 означает null-terminated strings (не newline terminated)
awk '{sum+=$1}. END {print sum}': Суммируем размеры файлов, выводимых предыдущей командой

И для справки, другим способом будет
find . -type f -iname '*.jpg' -print0 | du -c --files0-from=-

10
27.01.2020, 19:28

Если список файлов слишком велик, чтобы его можно было передать в один вызов du -c, то в системе GNU можно сделать:

find . -iname '*.jpg' -type f -printf '%b\t%D:%i\n' |
  sort -u | cut -f1 | paste -sd+ - | bc

(размер, выраженный в количестве блоков по 512 байт). Как и du, он пытается считать жесткие ссылки только один раз. Если вас не волнуют жесткие ссылки, вы можете упростить это до:

(printf 0; find . -iname '*.jpg' -type f -printf +%b) | bc

Если вы хотите, чтобы размер вместо диска использовался, замените %b на %s. Затем размер будет выражен в байтах

.
4
27.01.2020, 19:28

Упомянутые до сих пор решения неэффективны (exec стоит дорого) и требуют дополнительной ручной работы для суммирования, если список файлов длинный, или они не работают на Mac OS X. Следующее решение очень быстрое, работает на любой системе и выдает общий ответ в ГБ (уберите /1024, если хотите видеть общий ответ в МБ): find . -iname "*.jpg" -ls |perl -lane '$t += $F[6]; print $t/1024/1024/1024 . "GB"''

2
27.01.2020, 19:28

Улучшение отличного ответа SHW, чтобы заставить его работать с любым языком, как Zbyszek уже указал в своем комментарии:

LC_ALL=C find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
2
27.01.2020, 19:28

du естественно обходит иерархию каталогов, а awk может выполнять фильтрацию, поэтому может быть достаточно чего-то вроде этого:

du -ak | awk 'BEGIN {sum=0} /\.jpg$/ {sum+=$1} END {print sum}'

Это работает без GNU.

2
27.01.2020, 19:28

Окончательный ответ:

{ find <DIR> -type f -name "*.<EXT>" -printf "%s+"; echo 0; } | bc

и даже более быстрая версия, не ограниченная ОЗУ, но требующая GNU AWK с поддержкой bignum:

find <DIR> -type f -name "*.<EXT>" -printf "%s\n" | gawk -M '{t+=$1}END{print t}'

Эта версия имеет следующие особенности:

  • все возможности find , чтобы указать файлы, которые вы ищете
  • поддерживает миллионы файлов
    • другие ответы здесь ограничены максимальной длиной списка аргументов
  • только появляются 3 простых процесса с минимальной пропускной способностью канала
    • многие ответы здесь порождают процессы C + N, где C - некоторая константа, а N - количество файлов
  • не беспокоит манипуляции со строками
    • эта версия не выполняет никаких greping или regexing
    • хорошо, find выполняет простое сопоставление имен файлов с использованием подстановочных знаков
  • необязательно форматирует сумма в удобочитаемой форме (например, 5,5K , 176,7M , ...)
    • для этого добавить | numfmt --to = si
19
27.01.2020, 19:28

Еще бы

ls -al <directory> | awk '{t+=$5}END{print t}}'

Предположим, вы ищете в одном каталоге. Если вы хотите посмотреть текущий каталог и под ним

ls -Ral <directory> | awk '{t+=$5}END{print t}}'
0
09.03.2020, 15:38

Это то, что сработало для меня.

find -type f -iname *.jpg -print0 | du -ch --files0-from=- | grep total$
1
29.03.2020, 15:03

Другой вариант использования stat вместо du

stat -L -c %s ** | awk '{s+=$1} END {printf "%.0f\n", s}'

См. ответ Жиля об использовании**

0
12.04.2020, 13:33

Теги

Похожие вопросы