поиск каталогов, содержащих один файл, и отсутствие другого

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

find parent_directory -mindepth 1 -maxdepth 1 -type d '!' -exec sh -c 'ls -1 "{}"|egrep -i -q "^file_name$"' \; -print 

но теперь я хочу использовать результирующие каталоги, чтобы проверить, содержат ли они другой файл, но я не могу этого сделать в расширенном однострочном выражении. Возможно ли это как-то?

3 Solutions collect form web for “поиск каталогов, содержащих один файл, и отсутствие другого”

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

 for dir in */; do [ ! -e "$dir"/"$filename" ] || printf '%s\n' "$dir"; done 

И, чтобы увидеть, у кого из них есть другой файл:

 for dir in */; do [ ! -e "$dir"/"$filename1" ] && [ -e "$dir"/"$filename2" ] && printf '%s\n' "$dir"; done 

Или, в несколько более ясном синтаксисе:

 for dir in */; do if [ ! -e "$dir"/"$filename1" ]; then if [ -e "$dir"/"$filename2" ]; then printf '%s\n' "$dir"; fi fi done 

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

  • [ : это и сопровождающие ] являются синонимами для встроенного test (см. help [ или help test если используется оболочка sh-style). Это способы написания тестовых операций в оболочке.
  • -e : проверяет, существует ли файл / каталог и т. д. См. help test . Простой формат: [ -e file ] который вернет true, если file существует.
  • [ ! -e filename ] [ ! -e filename ] ! просто инвертирует тест. Итак, [ ! -e file ] [ ! -e file ] будет истинным, если file не существует.

Взятый вместе, это означает, что приведенная выше команда:

 ## Iterate over every directory (dirs only because of the '/' in '*/') ## saving each of them in the variable $dir. for dir in */; do ## If this $dir does not contain $filename1 if [ ! -e "$dir"/"$filename1" ]; then ## If this $dir does contain $filename2 if [ -e "$dir"/"$filename2" ]; then ## Print the directory name printf '%s\n' "$dir"; fi fi done 

Для запуска этого, конечно, вам нужно сначала установить $filename1 и $filename2 соответственно. Например:

 filename1="unwantedFile" filename2="wantedFile" 

Вы также можете определить свои требуемые каталоги:

 find . -maxdepth 2 -path '*/*/wanted.txt' -type f \ -execdir test ! -f unwanted.txt \; -execdir pwd \; 

Как это работает:

  • Мы ищем записи до глубины 2.
  • Опция -path дополнительно ограничивает их глубиной в 2 из-за наличия двух слэшей, так как maxdepth не позволяет идти дальше, а 2 изъятых косая черта препятствует переходу на глубину 2.
  • Запись wanted.txt, найденная на уровне глубины 2 лучше, является обычным файлом, обеспечиваемым -type f
  • Опция -execdir операцию к каталогу, в котором находится файл wanted.txt, и, следовательно, команда test будет искать там ненужный файл.
  • Затем просто печатать каталог (повышенный из-за -execdir ), где нежелательный файл не найден.
  • Без смысла, чтобы заполучить этот момент, каталог может содержать конкретный файл только один раз, поэтому операции -execdir запускаются один раз / каталог и только в тех каталогах, которые, по крайней мере, обязательно содержат необходимые файлы want.txt.

С помощью zsh для отображения каталогов в текущем каталоге, содержащих файл musthave а не файл mustnothave :

 contain() [[ -e $REPLY/$1 || -L $REPLY/$1 ]] printf '%s\n' *(D/e(contain musthave)^e(contain mustnothave)) 

Обратите внимание, что выполнение:

 find ... -exec sh -c 'ls {}' \; 

не только не переносима, но также является уязвимостью в отношении ввода команд. Например, если есть каталог с именем $(reboot) или ;reboot , который запускает строки командной строки ls $(reboot) или ls ;reboot вызывающие перезагрузку. {} никогда не должен быть встроен в аргумент кода ( sh или любой другой язык), где он может быть неверно истолкован. Использование:

 find ... -exec sh -c 'ls "$1"' sh {} \; 

вместо.

  • Восстановить права доступа к системному файлу
  • Как объединить два файла разных строк и столбцов и вывести соответствующие строки с помощью колонок?
  • Функционал posix_fadvice / POSIX_FADV_DONTNEED в Linux?
  • Дублировать файл x раз в командной оболочке
  • идентифицировать недостающие файлы в папке
  • Удаление дубликатов файлов, но игнорирование определенных строк (например, встроенная метка времени)
  • Предоставить пользователю разрешение на доступ к файлам в каталоге
  • Почему файлы tar и gzip обычно имеют расширение файла?
  • выпуск разрешения файла по умолчанию для пользователя rhel 6
  • Вывод команды подстановки grepping ls вызывает ошибку
  • Перемещение файлов из подпапок в родительскую папку в более крупном каталоге
  • Interesting Posts

    Cron не может получить доступ к моему домашнему каталогу при выходе из системы

    Установка плагина для quodlibet как патча

    создать плоский архив tar: игнорирование всех родителей при добавлении папок

    hdparm -S60 / dev / sda (работает нормально, но каждые 30 минут HDD просыпается и вращается, хотя и не используется).

    incrontab сообщает об изменении файла, который не существует

    Как я могу сделать алиасы оболочки доступными при обстреле из Vim?

    Почему записи в моем / proc / iomem – все 00000000-00000000?

    Shell Scripting: вычислить мощность числа с реальным числом в качестве показателя

    как удалить карантин из разрешений файлов в os x

    SSH с бастионным хостом и разными именами пользователей

    Как сжимать изображения с помощью тримажа?

    Я случайно удалил файл sudoers в Mac OS X; есть ли способ его восстановить?

    Аппетитно, как репозиторий RPM

    Почему у вас много счетов? Я единственный пользователь

    Qemu Arm как перейти через PCI-карту

    Linux и Unix - лучшая ОС в мире.