Найдите и используйте для вычисления общего размера против xargs

Вопрос или проблема

Может кто-нибудь подтвердить, что следующая строка кода даст общее читаемое человеком размер всех каталогов, которые 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 в stdin du. Однако 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. Однако, в приведенной вами строке возникают несколько важных моментов, которые требуют внимания.

Основные проблемы в исходной команде

  1. Игнорирование ввода через стандартный поток: Ваша команда find -type d -name *log* | du -hcs будет эквивалентна просто вызову du -hcs, поскольку команда du игнорирует стандартный ввод. Для корректного выполнения необходимо передавать найденные пути как аргументы, что можно реализовать с помощью утилиты xargs.

  2. Расширение имени файла: Необходимо обернуть шаблоны имен в одинарные кавычки ('*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 позволит вам точно и эффективно вычислить общий размер всех директорий, соответствующих заданному шаблону. Это подход, который будет работать корректно в большинстве ситуаций, обеспечивая точность и надежность в вычислениях.

Оцените материал
Добавить комментарий

Капча загружается...