Отримайте список імен каталогів з find


35

Я знаю, що можу це зробити, щоб отримати список імен каталогів:

find . -type d -maxdepth 1 

Вихід виглядає приблизно так:

.
./foo
./bar

Я вважаю за краще лістинг без ./. Чи є спосіб знайти пошук, щоб виводити лише необроблені імена?

Я спробував відправити список до 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. Жоден із printfваріантів POSIX не згадується, і деякі інші findверсії, схоже, не підтримуються . Знайти GNU можна встановити в більшості місць, тому в цьому сенсі він є портативним.
Тор

1
також додайте, -mindepth 1якщо ви хочете позбутися від.
Paweł Prażak,

18

Оновлення:

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

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

Дасть вам імена, по одному на рядок, без нахилів


4
@downvoter .. downvote без пояснення не допомагає нікому (ОП, SO або мене). Це функціональне рішення питання ОП. Я радий виправити помилку, якщо відповідь вказана або покращена, але для цього потрібні конструктивні відгуки, а не просто анонімне "натискання".
Левон

1
Я той, хто зволив голос, коли ваша відповідь включала розбір ls. У той же час я опублікував посилання про те, чому це погана ідея щодо іншої відповіді, яку видалили з того часу. На той час було лише 2 відповіді, і причина здавалася очевидною. Я радий, що ти вказав на неоднозначність, і ось моє пояснення. Для протоколу я перетворив свою позицію на позицію, оскільки я згоден з вашою поточною відповіддю.
rahmu

@rahmu Давати пояснення своєму голосному голосу в іншому питанні для мене не корисно (і лише очевидно для вас). Крім того, хоча це краще рішення, рішення, яке я розміщував раніше, працювало чудово (так, я знайомий з вашим посиланням "не використовуйте ls" - але воно не застосовується наосліп у всіх випадках). Якщо у вас є зустрічний приклад того, чому моє початкове рішення не працювало б, я хотів би це знати (щоб я насправді щось міг навчитися цьому), інакше ви просто розміщуєте посилання і не пропонуєте нічого конструктивного.
Левон

Подумайте, що \nв імені каталогу є ім'я, яке ви не можете використовувати cut, щоб отримати його (це те, що ви робили, коли я звертався з вами). Є кілька випадків, коли lsне веде себе небезпечно, і майже завжди безпечніше використовувати інший спосіб.
rahmu

9

Використовуючи пошук GNU, ви можете використовувати -mindepth, щоб запобігти збігу знаходження поточного каталогу:

find . -type d -maxdepth 1 -mindepth 1

Оскільки ви цим не займаєтесь рекурсивно, ви можете використовувати глобус bash:

echo */

Додавання контуру / в глобус призведе до узгодження лише каталогів.


1
*/пропускає крапкові файли та включає символьні посилання. Це може бути або не бути проблемою.
Жил "ТАК - перестань бути злим"

@Gilles - Завжди буде пропущено символьні посилання, але dotfiles залежить від того, встановлено чи ні dotglob.
Йорданм

6

Дозвольте sedвидалити ці два символи:

find . -maxdepth 1 -type d | sed -e 's/^\.\///'


2

Я зазвичай використовую:

find * -type d

Але я не знаю, чи це правильний спосіб робити те, що ти хочеш.


1
Якщо ви збираєтесь дозволити оболонці розширити всі назви файлів, навіщо взагалі використовувати пошук?
Йорданм

@jordanm Вибір лише каталогів. echo */зробив би те ж саме, більш-менш (він не вистачає точкових файлів і включає символьні посилання), але потім joachim запитає, як видалити остаточний /.
Жил 'SO- перестань бути злим'

0

У AIX параметр 'maxdepth' не працює.

Загалом для мене це працює:

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


0

Те, що ви шукаєте, називається basename, воно ігнорує структуру каталогу Unix

Приклад нижче:

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

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


Деякі додаткові відомості:

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

ПРИМІТКА: findпараметри не є позиційними (-maxdepth впливає на тести, визначені перед ним, а також на ті, що вказані після нього).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.