-1

Учитывая тип файла .txt, найдите все каталоги, которые имеют только этот тип файла.

Например

a--
   b-- 1.txt
   c--
      |
       ---- 2.jpg
       ---- 3.txt

Команда должна выводить только b не c .

1 ответ1

1
find . -type d -execdir sh -c '
   [ "$(find "$1" -maxdepth 1 -type f -name "*.txt" -print -quit | wc -l)" -gt 0 ] &&
   [ "$(find "$1" -maxdepth 1 -type f ! -name "*.txt" -print -quit | wc -l)" -eq 0 ]
   ' find-sh {} \; -print

Внешняя find поставляет каталоги, которые нужно изучить. Два внутренних find -s проверяют, есть ли в каталоге хотя бы один файл .txt и нет файлов не .txt . Оболочка sh реализует логику с помощью [ … ] и && .

Заметки:

  • -maxdepth не требуется для POSIX. Для подхода POSIX см. Этот вопрос.
  • -quit не требуется POSIX. Это действие заставляет find выход, как только сообщается о любом подходящем файле. Это полезно, потому что нам нужен максимум один соответствующий файл для получения результата с помощью wc -l и [ … ] , поэтому выход из программы раньше экономит время. Без -quit вся команда будет работать, она будет медленнее, когда есть много файлов. В качестве альтернативы вы можете использовать find … | head -n 1 | wc -l ; в этом случае head прервет канал после первого найденного файла, wc выдаст результат, но find прерванный канал только тогда, когда (если) попытается написать еще одну строку. И это компромисс: head может сэкономить вам некоторое время и ресурсы, но (как отдельный процесс) ему нужно время и ресурсы, которые будут порождаться дважды в каждом каталоге.
  • Пути с символами новой строки (если таковые имеются) будут wc -l но это не имеет значения, потому что эти дополнительные символы новой строки могут добавить к счетчику, только если "правильное" число в любом случае ненулевое, и нам нужно только знать, является ли результат ноль или нет.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .