Можем ли мы передать список каталогов из команды find в качестве аргумента другой команде find и выполнить md5sum?

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

Я хочу перечислить все директории в текущей директории и передать эти директории в качестве аргумента другой команде find. Пример ниже объясняет это правильно.

$ find . -maxdepth 1 -type d
.
./dir1
./dir2
./dir3
./dir4

$ echo -e "\n" ; find (вышеуказанные директории как аргумент) -exec md5sum {} +

Таким образом, я получаю контрольные суммы для всех файлов в папке по отдельности, разделенные пробелом. Я думаю, что вышеуказанный пример правильно объясняет проблему. Извините за мой плохой английский, у меня очень мало знаний о командах Linux, пожалуйста, простите меня. Спасибо заранее.

Вы можете сделать следующее:

find . ! -name . -prune -type d -exec sh -c '
  for dir do
    printf "\n\n"
    find "$dir" -type f -exec md5sum {} +
  done' sh {} +

(здесь мы экранируем } внутри встроенного кода sh с помощью \, чтобы {} не появлялся там, потому что в некоторых реализациях find внешний find заменит его на путь директории, даже если {} не является аргументом).

Я также заменил нестандартный -maxdepth 1 на стандартный ! -name . -prune, который здесь больше похож на -mindepth 1 -maxdepth 1, так как он пропускает . (на глубине 0), что, как я подозреваю, здесь вам и нужно.

Если вы используете zsh, вы можете сделать это без необходимости в find и с отсортированным списком директорий и файлов:

for dir in *(ND/); do
  print '\n'
  files=( $dir/**/*(ND.) )
  (( $#files )) && md5sum -- $files
done

Вы также можете пропустить печать разделителя при первом запуске и для директорий без обычных файлов:

run=0
for dir in *(NDF); do
  files=( $dir/**/*(ND.) )
  if (( $#files )); then
    (( run++ )) && print '\n'
    md5sum -- $files
  fi
done

Будьте осторожны на системах, где есть ограничение на размер списка аргументов, которые могут быть переданы команде при выполнении (большинство из них), выполнение md5sum может не удаться, если в (и ниже) одной директории много обычных файлов. Вам может потребоваться использовать zargs, чтобы обойти это ограничение. find‘s -exec cmd {} + автоматически разбивает этот список.

Ответ или решение

Да, вы можете передать список директорий, найденный с помощью команды find, в другую команду find, чтобы выполнить md5sum для файлов в каждой директории. Приведу пример того, как это можно сделать.

Пример использования find с md5sum

Допустим, вы хотите получить контрольные суммы.md5 для всех файлов в директориях в текущем каталоге. Вы можете использовать следующую команду:

find . ! -name . -prune -type d -exec sh -c '
  for dir do
    printf "\n\n"
    find "$dir" -type f -exec md5sum {} +
  done' sh {} +

Объяснение команды:

  1. find . ! -name . -prune -type d: Эта часть находит все директории в текущем каталоге, при этом пропуская саму директорию ..

    • ! -name . избегает обработки текущей директории.
    • -prune предотвращает рекурсивный поиск в найденных директориях.
    • -type d указывает, что нужно искать только директории.
  2. -exec sh -c '...' sh {} +: Эта конструкция запускает командную оболочку sh, передавая ей найденные директории как аргументы.

    • Внутри оболочки идет цикл for dir do ... done, который проходит по всем найденным директориям.
    • printf "\n\n" выводит два перехода на новую строку для удобства отображения.
  3. find "$dir" -type f -exec md5sum {} +: Внутри цикла мы вызываем find снова для каждой директории, чтобы найти все файлы (-type f) и вычислить их контрольные суммы с помощью md5sum.

Важно:

  • Обязательно экранируйте фигурную скобку {} внутри тела sh -c, чтобы избежать неправильной подстановки имени файла. Убедитесь, что она экранирована, иначе find может подставить путь к директории вместо ожидаемого аргумента.
  • Если в директориях достаточно много файлов, может возникнуть ошибка, если количество аргументов превышает лимит операционной системы. В этом случае имеет смысл использовать find с -exec ... +, который автоматически обрабатывает это разделение аргументов.

Альтернативный способ с помощью zsh:

Если вы используете zsh, то можно выполнить аналогичную задачу без использования find:

run=0
for dir in *(NDF); do
  files=( $dir/**/*(ND.) )
  if (( $#files )); then
    (( run++ )) && print '\n'
    md5sum -- $files
  fi
done

Объяснение для zsh версии:

  1. *(NDF) — это расширение, которое ищет все директории, игнорируя пустые.
  2. files=( $dir/**/*(ND.) ) находит все файлы в текущей директории и поддиректориях, включая скрытые.
  3. Проверяет, есть ли найденные файлы с помощью if (( $#files )). Если есть, то выводит переход на новую строку и вычисляет контрольные суммы с помощью md5sum.

Эти методы позволяют эффективно получить контрольные суммы файлов в директориях. Если у вас есть дополнительные вопросы или нужны уточнения, пожалуйста, дайте знать!

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

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