Получить список имен каталогов с помощью find

35

Я знаю, что могу сделать это, чтобы получить список имен каталогов:

find . -type d -maxdepth 1 

Вывод выглядит так:

.
./foo
./bar

Я предпочитаю листинг без ./. Есть ли способ получить find для вывода только необработанных имен?

Я попытался отправить список в stat, чтобы отформатировать его, но это просто дает мне тот же результат:

find . -type d -maxdepth 1 -print0 | xargs -0 stat -f '%N'
Иоахим
источник
так вы хотите foo bar ...все на одной линии без ./спереди?
Левон
Это чисто по косметическим / эстетическим причинам или вы пытаетесь что-то сделать с выходом?
jw013

Ответы:

42

С GNU findвы можете использовать -printfопцию:

find . -maxdepth 1 -type d -printf '%f\n'

Как отметил Павел в комментариях, если вы не хотите, чтобы текущий каталог отображался в списке, добавьте -mindepth 1, например:

find . -mindepth 1 -maxdepth 1 -type d -printf '%f\n'
Тор
источник
Я не могу найти упоминания об этой -printfопции в последней спецификации POSIX, и мне интересно, насколько она портативна ...
rahmu
@rahmu: Это было проверено с помощью GNU find. printfPOSIX не упоминает ни об одном из этих параметров, и, похоже, они не поддерживаются некоторыми другими findверсиями. GNU find может быть установлен в большинстве мест, поэтому в этом смысле он переносим.
Тор
1
также добавьте, -mindepth 1если вы хотите избавиться от.
Paweł Prażak
18

Обновить:

Более короткая альтернатива:

 find . -maxdepth 1 -type d | cut -c 3-

Даст вам имена, по одному в строке, без слешей

Левон
источник
4
@downvoter .. downvote без объяснения не помогает никому (ОП, SO или меня). Это функциональное решение вопроса ОП. Я рад исправить ошибку, если указал, или улучшить ответ, но для этого требуется конструктивная обратная связь, а не просто анонимный «щелчок».
Левон
1
Я тот, кто отрицал, когда ваш ответ включал в себя анализ ls. В то же время я разместил ссылку о том, почему это плохая идея в другом ответе, который был удален с тех пор. В то время было только 2 ответа, и причина казалась очевидной. Я рад, что вы указали на двусмысленность, и вот мое объяснение. Для протокола, я превратил свое отрицательное голосование в положительное, потому что я согласен с вашим текущим ответом.
Рахму
@rahmu Объяснение вашего отрицательного голоса в другом вопросе не помогает мне (и только очевидно для вас). Кроме того, хотя это и лучшее решение, решение, которое я выложил ранее, работало отлично (да, я знаком с вашей ссылкой «не использовать ls» - но она не применяется вслепую во всех случаях). Если у вас есть встречный пример того, почему мое первоначальное решение не сработало, я бы хотел узнать это (чтобы я мог чему-то научиться из этого), иначе вы просто публикуете ссылку и не предлагаете ничего конструктивного.
Левон
Учтите, что \nв каталоге есть имя, которое вы не можете использовать cut, чтобы получить его (что вы и делали, когда я отказался от вас). Есть несколько случаев, когда lsне ведет себя опасно, и почти всегда безопаснее использовать другой способ.
Рахму
9

Используя GNU find, вы можете использовать -mindepth для предотвращения поиска find в текущем каталоге:

find . -type d -maxdepth 1 -mindepth 1

Поскольку вы не делаете это рекурсивно, вы можете использовать bash glob:

echo */

Добавление конечного / к глобу вызовет сопоставление только каталогов.

jordanm
источник
1
*/пропускает точечные файлы и включает в себя символические ссылки. Это может или не может быть проблемой.
Жиль "ТАК - перестань быть злым"
@Gilles - он всегда будет пропускать символические ссылки, но точечные файлы зависят от того, установлен ли dotglob.
Иордания
6

Давайте sedудалим эти два символа:

find . -maxdepth 1 -type d | sed -e 's/^\.\///'
Birei
источник
6

Я бы лучше использовал:

 find ./ -type d -maxdepth 1 -exec basename {} \;
user1293137
источник
2

Я обычно использую:

find * -type d

Но я не знаю, правильно ли это делать то, что вы хотите.

Франческо Турко
источник
1
Если вы хотите, чтобы оболочка расширила все имена файлов, зачем вообще использовать find?
Иордания
@jordanm Для выбора только каталогов. echo */будет делать то же самое, более или менее (он пропускает точечные файлы и содержит символические ссылки), но затем joachim спрашивает, как удалить финал /.
Жиль "ТАК - перестань быть злым"
0

В AIX параметр maxdepth не работает.

В целом это работает для меня:

find ./ -type d | cut -d"/" -f2 | sort -u

user1656294
источник
0

То, что вы ищете, называется basename, оно игнорирует структуру каталогов unix

Пример ниже:

find /any/path/you/want -maxdepth 1 -type d -exec basename {} \;

он исключит для вывода даже путь dir, избавляя от необходимости cd перед выполнением команды


Некоторая дополнительная информация:

Я бы передал в -execкачестве аргумента вместо |(трубу) другую команду для вывода (избегая того, чтобы вторая команда проходила по каждой строке вывода, сказав, что в зависимости от вывода это может улучшить производительность сценария)

ПРИМЕЧАНИЕ: findпараметры не являются позиционными (-maxdepth влияет на тесты, указанные до него, а также на те, которые указаны после него).

gonzalesraul
источник