Вывод списка только каталогов, использующих ls в bash: экзамен

776

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

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

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

  • 7
    См. Редактирование этого ответа unix.stackexchange.com/a/75047/32647, объясняющее, что на самом деле означает -d .
Теги:
directory
ls

25 ответов

784
Лучший ответ

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

  • 66
    Обратите внимание, что */ не будет соответствовать ни одной скрытой папке. Чтобы включить их, либо укажите их явно как ls -d .*/ */ , dotglob установите опцию dotglob в Bash.
  • 0
    Я получаю сообщение об ошибке ls: cannot access */. No such file or directory Почему консоль не отображает это как параметр? Я использую cygwin
Показать ещё 9 комментариев
431

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

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" 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 я in $(ls -d */); do echo ${i%%/}; done for я in $(ls -d */); do echo ${i%%/}; done
Вот что я получил:

cs  
draft  
files  
hacks  
masters  
static

Если вы хотите, чтобы конечным символом был символ '/', команда будет: for я in $(ls -d */); do echo ${i}; done for я in $(ls -d */); do echo ${i}; done

cs/  
draft/  
files/  
hacks/  
masters/  
static/
  • 2
    NB. 3 был заметно медленнее, чем другие для меня. В каталоге я проверил: 1 .012s, 2 .016s, 3 .055s, 4 .021s.
  • 0
    @isomorphismes, как ты измерил время? Какими средствами? Кстати, я должен сказать, что № 1 мой любимый.
Показать ещё 12 комментариев
81

Я использую:

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

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

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

  • 16
    Параметр -1 для ls будет также выводиться в формате с одним столбцом, как в ls -1 -d */ .
  • 3
    @ user29020 Следует отметить, что -1 прежнему выводит косую черту для каждой записи.
Показать ещё 3 комментария
47

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

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

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

find /home/alice/Documents -type d
  • 0
    Чтобы соответствовать вопросу (но с точечными файлами), первым должно быть следующее: find /home/alice/Documents -maxdepth 1 -mindepth 1 -type d противном случае вы сами включаете /home/alice/Documents . Чтобы включить символические ссылки на каталоги, используйте префикс -L
  • 0
    Это кажется самым разумным решением, так как поиск - это инструмент, который фактически создан для этой задачи. Вы можете исключить первый результат - ./ для текущего каталога - отправив команду grep -v '^ \ ./$'
31

4 (больше) Надежные параметры.

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

1.- echo.

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).
  • каждая новая строка в имени запустит новую команду эха.

4.- Функция

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

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

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

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

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

  • 0
    Я думаю, что вы должны заменить слово Safe на Reliable. Ваш пост заставляет меня думать, что другие решения «небезопасны» (уязвимы или могут использоваться).
  • 1
    @AmadoMartinez Совершено общее с / безопасно / надежно /. Лучше?
15

Команда 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

Дополнительные аргументы можно увидеть с помощью man tree

11

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

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

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

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

\ ls -d */

9

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

alias lsd='ls -ld */'

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

  • 0
    Не могли бы вы просто использовать? ls -l путь | Grep Dr
  • 4
    "тогда lsd даст желаемый результат." я смеюсь
Показать ещё 1 комментарий
7

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

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}'
  • 0
    Если вам нужно узнать больше о awk , пожалуйста, посмотрите на этот ответ
  • 0
    По сравнению с другими ответами первый вариант «ls .. | grep ... | awk» кажется чрезмерным сценарием.
Показать ещё 1 комментарий
6

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

ls -l | grep ^d

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

ls -l | grep -v ^d 

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

  • 0
    grep ^d - это строка grep, начинающаяся с d ....
6

для отображения списков папок без /

ls -d */|sed 's|[/]||g'
  • 2
    или ls -d1 */ | tr -d "/"
  • 0
    Не нужно вызывать внешнюю команду: set -- */; printf "%s\n" "${@%/}"
Показать ещё 2 комментария
5

Актуальное решение 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 '(?=/$)'
5

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

ls -d1 /Directory/Path/*;

  • 0
    На самом деле это довольно хорошее решение для отображения его построчно.
  • 0
    Это не будет перечислять только каталоги. Вы должны добавить косую черту: ls -d1 /Directory/Path/*/
4

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

for i in $(ls); do test -d $i && echo $i ; done
  • 1
    Пожалуйста, объясните, что делает этот код и как он связан с вопросом.
  • 1
    он запускает команду 'ls', затем просматривает выходной тест, если каждый из них является каталогом, и отображает эхо-запрос, если он ... работает, но есть лучшие способы
2

Использование Perl:

ls | perl -nle 'print if -d;'
2

FYI, если вы хотите распечатать все файлы в многострочном режиме, вы можете сделать ls -1, который будет печатать каждый файл в отдельной строке. file1 file2 файл3

2

*/ - это шаблон соответствия имени файла, который соответствует каталогам в текущем каталоге.

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

# 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'
}
2

Однострочный список для отображения каталогов только из "здесь".

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

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

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

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

1

Попробуй это. это будет работать на всех дистрибутивах -ltr | grep drw

1

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

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

Я частично решил с помощью:

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

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

0

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

ls -1d ./*/

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

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

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

ls -1d /some/folder/*/ | awk -F "/" "{print \$(NF-1)}"
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 permitted
 file - determine file type
 grep - searches for string named directory
 -d - to specify a field delimiter
 -f1 - denotes field 1

Ещё вопросы

Сообщество Overcoder
Наверх
Меню