Список только каталогов, использующих ls в Bash?


955

Эта команда выводит список каталогов по текущему пути: ls -d */

Что именно делает шаблон */?

И как мы можем дать абсолютный путь в приведенной выше команде (например ls -d /home/alice/Documents) для перечисления только каталогов по этому пути?


7
См. Редактирование этого ответа unix.stackexchange.com/a/75047/32647, где объясняется, что на -dсамом деле означает.
Евгений Сергеев

Ответы:


993

*/является шаблоном, который соответствует всем подкаталогам в текущем каталоге ( *будет соответствовать всем файлам и подкаталогам; /ограничивает его каталогами). Точно так же, чтобы вывести список всех подкаталогов в / home / alice / Documents, используйтеls -d /home/alice/Documents/*/


88
Обратите внимание, что */не будет соответствовать ни одной скрытой папки. Чтобы включить их, либо укажите их явно как ls -d .*/ */, либо установите dotglobпараметр в Bash.
Герго

1
@ytpillai Это происходит потому, что в списке нет подкаталогов. Вы получаете эту ошибку каждый раз, когда используете lsчто-то, чего не существует.
Гордон Дэвиссон

1
Хорошо, спасибо, я только что проверил это, и оказалось, что единственным каталогом является корневая папка.
ytpillai

1
@GordonDavisson Сообщение о сбое можно избежать с помощью опции bashshopt -s nullglob

4
@BinaryZebra Установка значения nullglob позволит избежать появления сообщения об ошибке, но может привести к еще большей путанице: с установленным значением nullglob и отсутствием подкаталогов ls */расширится до просто ls, что приведет к выводу списка всех файлов в текущем каталоге. Я уверен, что это не то, что вы хотите в этом случае.
Гордон Дэвиссон

481

Четыре способа сделать это, каждый с различным форматом вывода

1. Использование echo

Пример: echo */, echo */*/
Вот что я получил:

cs/ draft/ files/ hacks/ masters/ static/  
cs/code/ files/images/ static/images/ static/stylesheets/  

2. Использование lsтолько

Пример: ls -d */
Вот именно то, что я получил:

cs/     files/      masters/  
draft/  hacks/      static/  

Или как список (с подробной информацией): ls -dl */

3. Использование lsиgrep

Пример: ls -l | grep "^d" вот что я получил:

drwxr-xr-x  24 h  staff     816 Jun  8 10:55 cs  
drwxr-xr-x   6 h  staff     204 Jun  8 10:55 draft  
drwxr-xr-x   9 h  staff     306 Jun  8 10:55 files  
drwxr-xr-x   2 h  staff      68 Jun  9 13:19 hacks  
drwxr-xr-x   6 h  staff     204 Jun  8 10:55 masters  
drwxr-xr-x   4 h  staff     136 Jun  8 10:55 static  

4. Bash Script (не рекомендуется для имени файла, содержащего пробелы)

Пример: for i in $(ls -d */); do echo ${i%%/}; done
вот что я получил:

cs  
draft  
files  
hacks  
masters  
static

Если вы хотите, чтобы в качестве завершающего символа был символ «/», команда будет выглядеть так: for i in $(ls -d */); do echo ${i}; done

cs/  
draft/  
files/  
hacks/  
masters/  
static/

2
NB. 3был заметно медленнее, чем другие для меня. В каталоге, который я тестировал: 10,012, 20,016, 3 055 , 4021.
изоморфизм

@isomorphismes, как ты измерил время? Какими средствами? Кстати, я должен сказать, нет, 1это мой любимый.
Альберт

Альберт, я использовал timeфункцию Unix. /// Согласен, echo */умнее чем ls -d */.
изоморфизм

9
Две незначительные вещи, на которые стоит обратить внимание. ls -l | grep "^ d" отфильтровывает символические ссылки на каталоги, тогда как 'ls -d * /' отображает их. Кроме того, 'ls -d * /' завершается ошибкой, если в целевом каталоге вообще нет каталогов.
Зоран Павлович

15
Эта 1.опция вызовет серьезные проблемы при работе с именами папок с пробелами.
Шрикант Шарат

99

Я использую:

ls -d */ | cut -f1 -d'/'

Это создает один столбец без косой черты - полезно в сценариях.

Мои два цента.


18
-1Вариант lsбудет выводить в формате одного столбца , а также, как и в ls -1 -d */.
Калин

3
@ user29020 Следует отметить, что по- -1прежнему выводит косую черту для каждой записи.
Деннис

Когда я добавляю это .bashrcкак псевдоним, как мне добавить '/'?
РНК

@ РНК поздно, чтобы ответить, но для будущих людей: попробуйте убежать с обратной косой чертой? '\/'
Caek

1
Ломается, если есть ведущий слеш. Это удаляет только косые черты:| sed -e 's-/$--'
Виктор Сергиенко

62

Для всех папок без подпапок:

find /home/alice/Documents -maxdepth 1 -type d

Для всех папок с подпапками:

find /home/alice/Documents -type d

2
Чтобы соответствовать вопросу (но с точечными файлами), первым должно быть: в find /home/alice/Documents -maxdepth 1 -mindepth 1 -type dпротивном случае вы включаете /home/alice/Documentsсебя. Чтобы включить символические ссылки на каталоги, -L
добавьте

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

38

4 (более) надежных варианта.

Неупомянута звездочка *будет интерпретироваться как шаблон (Glob) с помощью оболочки.
Оболочка будет использовать его в расширении пути.
Затем он сгенерирует список имен файлов, которые соответствуют шаблону.
Простая звездочка будет соответствовать всем именам файлов в PWD (текущий рабочий каталог).
Более сложный шаблон, который */будет соответствовать всем именам файлов, оканчивающимся на /.
Итак, все каталоги. Вот почему команда:

1.- эхо.

echo */
echo ./*/              ### avoid misinterpreting filenames like "-e dir"

будет расширен (оболочкой) на echoвсе каталоги в PWD.


Чтобы проверить это: создайте каталог ( mkdir) с именем, подобным test-dir, и cdв него:

mkdir test-dir; cd test-dir

Создайте несколько каталогов:

mkdir {cs,files,masters,draft,static}   # safe directories.
mkdir {*,-,--,-v\ var,-h,-n,dir\ with\ spaces}  # some a bit less secure.
touch -- 'file with spaces' '-a' '-l' 'filename'    # and some files:

Команда echo ./*/останется надежной даже с нечетными именованными файлами:

./--/ ./-/ ./*/ ./cs/ ./dir with spaces/ ./draft/ ./files/ ./-h/
./masters/ ./-n/ ./static/ ./-v var/

Но пробелы в именах файлов делают чтение немного запутанным.


Если вместо того echo, чтобы мы использовали ls, оболочка - это то, что расширяет список имен файлов. Оболочка является причиной получения списка каталогов в PWD. -dВариант lsделает его перечисляют настоящий элемент каталога вместо содержимого каждого каталога (представленных по умолчанию).

ls -d */

Однако эта команда (несколько) менее надежна. Сбой с нечетными именованными файлами, перечисленными выше. Он захлебнется несколькими именами. Вы должны стереть один за другим, пока не найдете те, у кого проблемы.

2.- ls

GNU lsпримет --клавишу «конец опций» ( ).

ls -d ./*/                     ### more reliable BSD ls
ls -d -- */                    ### more reliable GNU ls

3.-Printf

Чтобы отобразить каждый каталог в отдельной строке (в одном столбце, аналогично ls -1), используйте:

$ printf "%s\n" */        ### Correct even with "-", spaces or newlines.

И, что еще лучше, мы могли бы убрать трейлинг /:

$ set -- */; printf "%s\n" "${@%/}"        ### Correct with spaces and newlines.

Попытка как это:

$ for i in $(ls -d */); do echo ${i%%/}; done

Сбой на:

  • некоторые имена ( ls -d */), как уже показано выше.
  • будет зависеть от стоимости IFS.
  • разделит имена на пробелы и табуляции (по умолчанию IFS).
  • каждая новая строка в имени запускает новую команду echo.

4.- Функция

Наконец, использование списка аргументов внутри функции не повлияет на список аргументов текущей запущенной оболочки. Просто:

$ listdirs(){ set -- */; printf "%s\n" "${@%/}"; }
$ listdirs

представляет этот список:

--
-
*
cs
dir with spaces
draft
files
-h
masters
-n
static
-v var

Эти параметры безопасны с несколькими типами нечетных имен файлов.


Я думаю, что вы должны заменить слово Safe на Reliable. Ваш пост заставляет меня думать, что другие решения являются «небезопасными» (уязвимыми или эксплуатируемыми.)
Амадо Мартинес

1
@AmadoMartinez Сделано общее s / безопасно / надежно /. Лучше?

21

Команда treeтакже очень полезна здесь. По умолчанию он показывает все файлы и каталоги на полную глубину, а некоторые символы ascii показывают дерево каталогов.

$ tree
.
├── config.dat
├── data
   ├── data1.bin
   ├── data2.inf
   └── sql
|      └── data3.sql
├── images
   ├── background.jpg
   ├── icon.gif
   └── logo.jpg
├── program.exe
└── readme.txt

Но если мы хотим получить только каталоги, без дерева ascii и с полным путем из текущего каталога, вы можете сделать:

$ tree -dfi
.
./data
./data/sql
./images

Аргументы:

-d     List directories only.
-f     Prints the full path prefix for each file.
-i     Makes tree not print the indentation lines, useful when used in conjunction with the -f option.

И если вам нужен абсолютный путь, вы можете начать с указания полного пути к текущему каталогу:

$ tree -dfi "$(pwd)"
/home/alice/Documents
/home/alice/Documents/data
/home/alice/Documents/data/sql
/home/alice/Documents/images

А чтобы ограничить количество подкаталогов, вы можете установить максимальный уровень подкаталогов с помощью -L level, например:

$ tree -dfi -L 1 "$(pwd)"
/home/alice/Documents
/home/alice/Documents/data
/home/alice/Documents/images

Больше аргументов можно увидеть с человеком дерева


15

Если вам интересно, почему вывод команды 'ls -d * /' дает вам две косые черты, например:

[prompt]$ ls -d */    
app//  cgi-bin//  lib//        pub//

Возможно, это связано с тем, что где-то в ваших конфигурационных файлах оболочки или сессии псевдоним команды ls указан в версии ls, содержащей флаг -F. Этот флаг добавляет символ к каждому выходному имени (это не простой файл), указывая на то, что это такое. Таким образом, одна косая черта соответствует шаблону '* /', а другая косая черта - это индикатор добавленного типа.

Чтобы избавиться от этой проблемы, вы, конечно, можете определить другой псевдоним для ls. Однако, чтобы временно не вызывать псевдоним, вы можете добавить к команде обратную косую черту:

\ ls -d * /


11

Я просто добавляю это в мой .bashrcфайл (вы также можете просто напечатать его в командной строке, если вам нужно / нужно только для одного сеанса)

alias lsd='ls -ld */'

тогда lsd выдаст желаемый результат.


Не могли бы вы просто использовать? ls -l путь | grep dr
jrobertsz66

5
"тогда lsd даст желаемый результат." Я смеюсь
fbafelipe

1
По моему опыту, это дает результат.
Тодд

Я использую 'lad' (список всех каталогов), и я также включил '. * /', Чтобы включить скрытые каталоги. Конечно, недосказанность не потеряна и для меня.
DryLabRebel

11

Актуальное lsрешение, включая символические ссылки на каталоги

Многие ответы здесь на самом деле не используют ls(или используют только в тривиальном смысле ls -d, когда используют подстановочные знаки для фактического соответствия подкаталога. Истинное lsрешение полезно, поскольку оно позволяет использовать lsпараметры для порядка сортировки и т. Д.

Исключая символические ссылки

lsБыло дано одно использование решения , но оно отличается от других решений тем, что исключает символические ссылки на каталоги:

ls -l | grep '^d'

(возможно перебирать sedили awkизолировать имена файлов)

Включая символические ссылки

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

ls -1p | grep '/$'

или, избавляясь от конечных слешей:

ls -1p | grep '/$' | sed 's/\/$//'

Мы можем добавлять опции по lsмере необходимости (если используется длинный список, -1он больше не требуется).

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

ls -1p | grep -P '(?=/$)'

9

Если скрытый каталог не требуется перечислять, я предлагаю:

ls -l | grep "^d" | awk -F" " '{print $9}'  

И если нужно перечислить скрытые каталоги, используйте:

ls -Al | grep "^d" | awk -F" " '{print $9}'

ИЛИ

find -maxdepth 1 -type d | awk -F"./" '{print $2}'

Если вам нужно узнать больше о awk, пожалуйста, посмотрите на этот ответ
PHP Learner

По сравнению с другими ответами первый вариант «ls .. | grep ... | awk» кажется чрезмерным сценарием.
Ларс Нордин

1
Вы предполагаете, что ни у каких каталогов нет пробелов в их именах.
Бенджамин Р

7

показывать списки папок без /

ls -d */|sed 's|[/]||g'

2
илиls -d1 */ | tr -d "/"
ccpizza

Не нужно вызывать внешнюю команду:set -- */; printf "%s\n" "${@%/}"

Мне нравится решение @wholanda. Мой немного короче раствор (проверено и работает): LS -d * / | SED 's | / || г'
Klor

Кроме того, имея lsdir псевдоним полезно: псевдоним lsdirs = "LS -d * / | СЭД 's | / || г'"
Klor

6

Вот что я использую

ls -d1 /Directory/Path/*;


На самом деле это довольно хорошее решение для отображения его построчно.
Николай Фрик

Он не будет содержать только каталоги. Вы должны добавить косую черту:ls -d1 /Directory/Path/*/
Skippy le Grand Gourou

6

Для просмотра только каталогов :

ls -l | grep ^d

для просмотра только файлов :

ls -l | grep -v ^d 

или также вы можете сделать как: ls -ld * /


4

Проверьте, является ли элемент каталогом с test -d:

for i in $(ls); do test -d $i && echo $i ; done

1
Пожалуйста, объясните, что делает этот код и как он связан с вопросом.
Кен YN

1
он запускает команду 'ls', затем просматривает результаты тестирования, если каждый из них является каталогом, и отображает эхо-запрос, если он ... работает, но есть более эффективные способы
ShoeLace

3

*/ шаблон сопоставления имен файлов, соответствующий каталогам в текущем каталоге

Чтобы перечислить только каталоги, мне нравится эта функция:

# long list only directories
llod () { 
  ls -l --color=always "$@" | grep --color=never '^d'
}

Поместите это в свой .bashrc.

Примеры использования:

llod       # long listing of all directories in current directory
llod -tr   # same but in chronological order oldest first
llod -d a* # limit to directories beginning with letter 'a'
llod -d .* # limit to hidden directories

ПРИМЕЧАНИЕ: он сломается, если вы используете -iопцию. Вот исправление для этого:

# long list only directories
llod () { 
  ls -l --color=always "$@" | egrep --color=never '^d|^[[:digit:]]+ d'
}

3

К вашему сведению, если вы хотите распечатать все файлы в несколько строк, вы можете выполнить команду, ls -1которая будет печатать каждый файл в отдельной строке. файл1 файл2 файл3


3

Простой список текущего каталога, это будет:

ls -1d ./*/

Вы хотите, чтобы это было отсортировано и чисто?

ls -1d ./*/ | cut -c 3- | rev | cut -c 2- | rev | sort

Помните: заглавные буквы имеют различное поведение в сортировке


3

Попробуй это. Это работает для всех дистрибутивов Linux.

ls -ltr | grep drw

4
ls -l | grep '^d' | awk '{print $9}'
dw1

2

Однострочный список каталогов только из «здесь».

С количеством файлов.

for i in `ls -d */`; do g=`find ./$i -type f -print| wc -l`; echo "Directory $i contains $g files."; done

2

Я частично решил с:

cd "/path/to/pricipal/folder"

for i in $(ls -d .*/); do sudo ln -s "$PWD"/${i%%/} /home/inukaze/${i%%/}; done

ln: «/home/inukaze/./.»: can't overwrite a directory
ln: «/home/inukaze/../..»: can't overwrite a directory
ln: accesing to «/home/inukaze/.config»: too much symbolics links levels
ln: accesing to «/home/inukaze/.disruptive»: too much symbolics links levels
ln: accesing to «/home/inukaze/innovations»: too much symbolics links levels
ln: accesing to «/home/inukaze/sarl»: too much symbolics links levels
ln: accesing to «/home/inukaze/.e_old»: too much symbolics links levels
ln: accesing to «/home/inukaze/.gnome2_private»: too much symbolics links levels
ln: accesing to «/home/inukaze/.gvfs»: too much symbolics links levels
ln: accesing to «/home/inukaze/.kde»: too much symbolics links levels
ln: accesing to «/home/inukaze/.local»: too much symbolics links levels
ln: accesing to «/home/inukaze/.xVideoServiceThief»: too much symbolics links levels

Ну, это сводит меня, часть мэра :)


2

Чтобы сделать круг полным, чтобы найти путь к каждой папке, используйте комбинацию ответа Альберта и Гордана, которые должны быть довольно полезными.

for i in $(ls -d /pathto/parent/folder/*/); do echo ${i%%/}; done

Вывод:

/pathto/parent/folder/childfolder1/
/pathto/parent/folder/childfolder2/
/pathto/parent/folder/childfolder3/
/pathto/parent/folder/childfolder4/
/pathto/parent/folder/childfolder5/
/pathto/parent/folder/childfolder6/
/pathto/parent/folder/childfolder7/
/pathto/parent/folder/childfolder8/


1

Вот что я использую для перечисления только имен каталогов:

ls -1d /some/folder/*/ | awk -F "/" "{print \$(NF-1)}"

1

Чтобы ответить на оригинальный вопрос, не */имеет ничего общего с lsper se; это делается shell / Bash, в процессе, известном как globbing .

Именно поэтому echo */и ls -d */выводим одинаковые элементы. ( -dФлаг lsвыводит имена каталогов, а не содержимое каталогов.)


1

Вот вариант с использованием дерева, который выводит имена каталогов только в отдельных строках, да, это уродливо, но эй, это работает.

tree -d | grep -E '^[├|└]' | cut -d ' ' -f2

или с awk

tree -d | grep -E '^[├|└]' | awk '{print $2}'

Это, вероятно, лучше, однако, и сохранит /имя каталога после.

ls -l | grep "^d" | awk '{print $9}'

это выглядит как корейский!
Пасхалис

0
file *|grep directory

O / P (на моей машине) -

[root@rhel6 ~]# file *|grep directory
mongo-example-master:    directory
nostarch:                directory
scriptzz:                directory
splunk:                  directory
testdir:                 directory

Выше вывод может быть уточнен больше с помощью вырезать.

file *|grep directory|cut -d':' -f1
mongo-example-master
nostarch
scriptzz
splunk
testdir

* could be replaced with any path that's permitted
 file - determine file type
 grep - searches for string named directory
 -d - to specify a field delimiter
 -f1 - denotes field 1

0

Самая короткая команда из всех (на самом деле хак) для перечисления только каталогов. Введите абсолютный путь или относительный путь интересующего каталога и нажмите ввод, чтобы ввести интересующий каталог. Теперь введите cdи нажмите клавишу Tab . Только каталоги показаны сейчас.

user@ubuntu:~/Desktop$cd <tab key>

Приведенная выше команда теперь должна отображать только папки на рабочем столе . Самый короткий.


Это предполагает, что автозаполнение включено и может работать не во всех случаях. Кроме того, если вы хотите что-то сделать с этим, например, направить вывод во что-то, это не сработает. Но если вы просто видите результат, он работает быстро и просто.
lacostenycoder

Отлично! Я удалил "." И тогда все
заработало
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.