Использование на диске файлов, имена которых соответствуют регулярному выражению, в Linux?

Итак, во многих ситуациях я хотел знать, сколько моего дискового пространства используется тем, что, поэтому я знаю, от чего избавиться, конвертировать в другой формат, хранить в другом месте (например, DVD-диски с данными), переходить в другой раздел и т. д. В этом случае я смотрю на раздел Windows из SliTaz Linux загрузочный носитель.

в большинстве случаев я хочу размер файлов и папок, и для этого я использую NCurses-based ncdu:

ncdu

но в этом случае, мне нужен способ, чтобы получить размер все файлы, соответствующие регулярному выражению. Пример regex для .файлы BAK:

.*.bak$

Как получить эту информацию, учитывая стандартный Linux с основными утилитами GNU или busybox и?

Edit: вывод предназначен для синтаксического анализа скриптом.

6 ответов


Я предлагаю что-то вроде: find . -regex '.*\.bak' -print0 | du --files0-from=- -ch | tail -1

некоторые замечания:

  • на на find и --files0-from на du есть, чтобы избежать проблем с пробелами в именах файлов
  • регулярное выражение сопоставляется со всем путем, например ./dir1/subdir2/file.bak не только file.bak, поэтому, если вы измените его, примите это во внимание
  • я h флаг для du для создания" читаемого человеком " формата, но если вы хотите проанализировать вывод, вы может быть лучше с k (всегда использовать килобайт)
  • если убрать tail команда, вы дополнительно увидите размеры конкретных файлов и каталогов

Sidenote: хороший инструмент GUI для выяснения, кто съел ваше дисковое пространство FileLight. Он не делает regexes, но очень удобен для поиска больших каталогов или файлов, забивающих ваш диск.


du - Это мой любимый ответ. Если у вас есть фиксированная структура файловой системы, вы можете использовать:

du -hc *.bak

Если вам нужно добавить подкаталоги, просто добавить:

du -hc *.bak **/*.bak **/**/*.bak

etc etc

однако это не очень полезная команда, поэтому, используя вашу находку:

TOTAL=0;for I in $(find . -name \*.bak); do  TOTAL=$((TOTAL+$(du $I | awk '{print }'))); done; echo $TOTAL

что выведет общий размер в байтах всех файлов, которые вы ищите.

надеюсь, что это поможет.


запустите это в оболочке Bourne, чтобы объявить функцию, которая вычисляет сумму размеров всех файлов, соответствующих шаблону регулярных выражений в текущем каталоге:

sizeofregex() { IFS=$'\n'; for x in $(find . -regex "" 2> /dev/null); do du -sk "$x" | cut -f1; done | awk '{s+=} END {print s}' | sed 's/^$/0/'; unset IFS; }

(альтернативно, вы можете поместить его в скрипт.)

использование:

cd /where/to/look
sizeofregex 'myregex'

результатом будет число (в КИБ), в том числе 0 (если нет файлов, соответствующих вашему регулярному выражению).

если вы не хотите, чтобы он выглядел в других файловых системах (скажем, вы хотите ищите все .so файлы /, который является горой /dev/sda1, но не /home, который является горой /dev/sdb1 добавьте до find в функции выше.


предыдущие решения не работали должным образом для меня (у меня были проблемы с трубопроводом du) но следующее отлично сработало:

find path/to/directory -iregex ".*\.bak$" -exec du -csh '{}' + | tail -1

на iregex option-нечувствительное к регистру регулярное выражение. Использовать regex если вы хотите, чтобы он был чувствителен к регистру.

если вы не знакомы с регулярными выражениями, вы можете использовать iname или name флаги (первые нечувствительны к регистру):

find path/to/directory -iname "*.bak" -exec du -csh '{}' + | tail -1

в случае, если вы хотите, чтобы размер каждого матча (а не просто объединенная сумма), просто оставьте команду piped tail:

find path/to/directory -iname "*.bak" -exec du -csh '{}' +

эти подходы избегают проблемы подкаталога в ответе @MaddHackers.

надеюсь, что это поможет другим в той же ситуации (в моем случае, найти размер всех DLL в .NET-решении).


если вы в порядке с glob-patterns, и вас интересует только текущий каталог:

stat -c "%s" *.bak | awk '{sum += } END {print sum}'

или

sum=0
while read size; do (( sum += size )); done < <(stat -c "%s" *.bak)
echo $sum

на %s директива для stat дает байты, а не килобайты.

если вы хотите спуститься в подкаталоги, с bash версии 4, Вы можете shopt -s globstar и использовать шаблон **/*.bak


принятый ответ предлагает использовать

find . -regex '.*\.bak' -print0 | du --files0-from=- -ch | tail -1

но это не работает в моей системе как du не знаю --files-0-from опция в моей системе. Только GNU du знает этот вариант, это ни одна из частей POSIX Standard (поэтому вы не найдете его во FreeBSD или macOS), и вы не найдете его на системы Linux на базе BusyBox (например, большинство встроенных систем Linux) или любая другая система Linux, которая не использует GNU du версия.

тогда есть ответ, предлагающий использовать:

find path/to/directory -iregex .*\.bak$ -exec du -csh '{}' + | tail -1

это решение будет работать до тех пор, пока не будет найдено слишком много файлов, как + означает, что find попробуем позвонить du С максимально возможным количеством обращений в одном вызове, однако, может быть максимальное количество аргументов (N), поддерживаемых системой, и если есть больше обращений, чем это значение,find будем называть du несколько раз, разделяя хиты на группы, меньшие или равные N элементам каждый и в этом случае результат будет неправильным и покажет только размер последнего du звонок.

наконец, есть ответ, используя stat и awk, который является хорошим способом сделать это, но он опирается на оболочку действуют таким образом, что только Баш 4.X или более поздняя версия поддерживает. Он не будет работать со старыми версиями, и если он работает с другими оболочками, это непредсказуемо.

решение POSIX conform (работает на Linux, macOS и любых вариантах BSD), которое не страдает никакими ограничениями и это, безусловно, будет работать с каждой оболочкой будет:

find . -regex '.*\.bak' -exec stat -f "%z" {} \; | awk '{s += } END {print s}'