Как отметить каталоги в выводе команды `find`?

Как отметить каталоги в выводе команды `find`?

Например, я ищу файлы и каталоги в некотором каталоге:

ubuntu@example:/etc/letsencrypt$ sudo find . -name example.com*
./archive/example.com
./renewal/example.com.conf
./live/example.com
ubuntu@example:/etc/letsencrypt$ 

Как я могу это отметить ./archive/example.comи ./live/example.comесть ли каталоги в выводе выше?

решение1

Распечатать тип файла вместе с именем можно с помощью -printf "%y %p\n":

$ sudo find . -name 'example.com*' -printf "%y %p\n"
d ./archive/example.com
f ./renewal/example.com.conf
d ./live/example.com

Использование -printfпредполагает GNU find(наиболее распространенная findреализация в системах Linux).

решение2

Найти дважды:

echo 'directories'
find . -name 'example.com*'   -type d

echo 'non-directories'
find . -name 'example.com*' ! -type d

Обратите внимание также на кавычки шаблона, используемого для проверки имени. Без кавычек оболочка попытается сопоставить строку с именами в текущем каталоге перед вызовом find. Если failglobопция оболочки была установлена ​​в bashоболочке или если NOMATCHопция оболочки в zshне была отключена, шаблон подстановки без кавычек, который ничему не соответствует, сгенерирует ошибку оболочки и findне будет вызван вообще.


В качестве альтернативы можно просто вывести косую черту в конце пути к каталогу (так ls -pбудут представлены каталоги):

find . -name 'example.com*' \( -type d -exec printf '%s/\n' {} \; -o -print \)

Вышеуказанная findкоманда сначала проверяет, что имя правильное. Если это так и это каталог, она вызывается printfдля вывода пути к каталогу со слешем в конце. Если это не каталог, -printиспользуется для простого вывода пути как есть.

С помощью GNU findэтот -exec printf '%s/\n' {} \;бит можно заменить на -printf '%p/\n'.

При использовании standard findвы также можете -exec printf '%s/\n' {} +вызывать внешнюю printfутилиту как можно реже, но это будет означать, что каталоги, скорее всего, будут выводиться в последнюю очередь или, по крайней мере, пакетами.


Другой альтернативой является использование для того, ls -pчтобы отличить каталоги от других типов файлов. При использовании ls -pкаталог будет указан с конечным /символом, как и выше.

find . -name 'example.com*' -exec ls -f -d -p {} +

Я использую -fздесь, чтобы избежать lsсортировки вывода и -dчтобы избежать перечислениясодержаниекаталогов.

Вы могли бы использовать ls -Fвместо ls -pto также поставитьдругойметки на типах файлов, отличных от каталогов. Например, исполняемые файлы будут иметь суффикс *, а символические ссылки будут иметь суффикс @.

Оба -pварианта -F-fи -d) являются стандартными опциями утилиты ls.

решение3

Вы можете использовать fileтак:

sudo find . -name "example.com*" -print0 | xargs  -0 sudo file

Пример вывода:

$ sudo find .  -name "example.com*"   -print0 | xargs  -0 sudo file
./example.com. big file: ASCII text
./example.com-dir:       directory
./example.com:           empty

решение4

Если вам нужен более портативный вариант, который будет работать с версиями *nix без -printfопции gnu (например, macOS), вы можете добавить косую черту в конец пути к каталогам следующим lsобразом:

find . -name "example.com*" -exec ls -dF {} \;

пример:

$ sudo find . -name "example.com*" -exec ls -dF {} \;
./archive/example.com/
./renewal/example.com.conf
./live/example.com/

Это также оказывается в формате, более подходящем для дальнейшей передачи большему количеству команд Unix.

Связанный контент