Вопрос или проблема
Может кто-нибудь подтвердить, что следующая строка кода даст общее читаемое человеком размер всех каталогов, которые FIND находит с “log” в названии?
find -type d -name *log* | du -hcs
Готовы?
find . -type d -name '*log*' -print0 | xargs -0 du -hcs
- Обрамите
*log*
в одинарные кавычки, иначе оболочка развернет его до того, какfind
его увидит. - Используйте
-print0
, чтобы разделить вывод find нулевыми символами дляxargs
- используйте
xargs -0
, чтобы передать каждое имя файла, отделенное нулем, изfind
в командную строкуdu
Просто, правда? 🙂
Ваш однострочник имеет две основные проблемы:
- Команда
find | du
передает выводfind
в stdindu
. Однакоdu
полностью игнорирует стандартный ввод, поэтому фильтрfind
полностью игнорируется, и предоставленная вами команда на самом деле эквивалентнаdu -hcs
. Решение состоит в том, чтобы использоватьxargs
, который передает список файлов как аргументы вdu
, илиdu --files0-from=-
(GNU coreutils). - Вам нужно экранировать звездочки в вашем шаблоне имени файла либо с помощью обратных слешей (
\*log\*
), либо с помощью одинарных кавычек ('*log*'
), иначе ваша оболочка попытается выполнить развертывание имени файла иfind
возможно вообще не увидит звездочки.
Некоторые дополнительные улучшения:
- В случае совпадений внутри совпадающих каталогов, таких как
./log/log/
, оба./log/
и./log/log/
будут переданы вdu
. Второй каталог будет проигнорированdu -s
, но вы можете увеличить производительность командыfind
, добавив действие-prune
. Это гарантирует, чтоfind
не будет углубляться в совпадающие каталоги. - Я добавляю
-print0
(и-0
вxargs
), чтобы избежать возможных проблем, например, с переводами строки в именах файлов, см. serverfault. - Я добавляю путь (
.
), чтобы сделать командуfind
совместимой с POSIX (и BSD).
Вот финальный однострочник:
find . -type d -name '*log*' -prune -print0 | xargs -0 du -hcs
Имейте в виду, что -name
чувствителен к регистру. Лично я почти всегда использую -iname
, который нечувствителен к регистру.
Дополнительная заметка: если вы используете du
из GNU coreutils, вы можете использовать его опцию --files0-from=-
и передавать пути файлов напрямую в du
, опуская xargs
. Согласно руководству, “это полезно, когда список имен файлов настолько длинный, что может превысить ограничение длины командной строки”.
find . -type d -name '*log*' -print0 | du --files0-from=- -hcs
Ответ или решение
Вычисление общего размера директорий с помощью find
и xargs
Ваша задача заключается в получении общего размера всех директорий, содержащих в своем имени слово "log". Для достижения этой цели может быть использован набор утилит find
и du
. Однако, в приведенной вами строке возникают несколько важных моментов, которые требуют внимания.
Основные проблемы в исходной команде
-
Игнорирование ввода через стандартный поток: Ваша команда
find -type d -name *log* | du -hcs
будет эквивалентна просто вызовуdu -hcs
, поскольку командаdu
игнорирует стандартный ввод. Для корректного выполнения необходимо передавать найденные пути как аргументы, что можно реализовать с помощью утилитыxargs
. -
Расширение имени файла: Необходимо обернуть шаблоны имен в одинарные кавычки (
'*log*'
), чтобы избежать преждевременного расширения имен файлов, которое выполняется оболочкой.
Рекомендуемое решение
Для более надёжного и корректного выполнения вашей задачи, мы будем использовать комбинацию команд find
, xargs
и du
. Вот как это должно выглядеть:
find . -type d -name '*log*' -prune -print0 | xargs -0 du -hcs
- Параметры команды:
find .
: выполняет поиск в текущем каталоге и подкаталогах.-type d
: ищет только директории.-name '*log*'
: фильтрует директории по имени, содержащему "log".-prune
: предотвращает дальнейшее углубление в найденные директории.-print0
: выводит результаты, разделённые нулевыми символами, чтобы избежать проблем при наличии пробелов или специальных символов в именах файлов.xargs -0
: принимает нулевую разделённость и передаёт результаты в командуdu
.
Альтернативный подход
Если вы используете GNU coreutils, вы можете обойтись без xargs
и передать результаты непосредственно в du
, используя следующий синтаксис:
find . -type d -name '*log*' -print0 | du --files0-from=- -hcs
Этот метод может быть полезен в случае большого количества результатов, когда общая длина командной строки может превысить допустимый предел системы.
Дополнительные рекомендации
- Чувствительность к регистру: Параметр
-name
чувствителен к регистру. Если вам необходимо игнорировать регистр, замените-name
на-iname
. - Производительность: Добавление параметра
-prune
помогает избежать ненужного сканирования подкаталогов, что ускоряет выполнение команды. - Обработка символов: Использование
-print0
и-0
необходимо для безопасной обработки имен файлов с пробелами или новыми строками.
Заключение
Таким образом, правильное использование find
, xargs
и du
позволит вам точно и эффективно вычислить общий размер всех директорий, соответствующих заданному шаблону. Это подход, который будет работать корректно в большинстве ситуаций, обеспечивая точность и надежность в вычислениях.