Использование на диске файлов, имена которых соответствуют регулярному выражению, в Linux?
Итак, во многих ситуациях я хотел знать, сколько моего дискового пространства используется тем, что, поэтому я знаю, от чего избавиться, конвертировать в другой формат, хранить в другом месте (например, DVD-диски с данными), переходить в другой раздел и т. д. В этом случае я смотрю на раздел Windows из SliTaz Linux загрузочный носитель.
в большинстве случаев я хочу размер файлов и папок, и для этого я использую NCurses-based 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}'