Перелік лише каталогів, що використовують ls у Bash?


954

Ця команда перераховує каталоги в поточному шляху: ls -d */

Що саме робить візерунок */?

І як ми можемо дати абсолютний шлях у наведеній вище команді (наприклад ls -d /home/alice/Documents) для переліку лише каталогів на цьому шляху?


7
Див. Редагування цієї відповіді unix.stackexchange.com/a/75047/32647 з поясненням того, що -dнасправді означає.
Євгеній Сергєєв

Відповіді:


991

*/- це шаблон, який відповідає всім підкаталогам у поточному каталозі ( *відповідатиме всім файлам і підкаталогам; /обмежує його до каталогів). Так само, щоб перелічити всі підкаталоги в / 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було помітно повільніше, ніж інші для мене. У довіднику я перевірив: 1.012s, 2.016s, 3 .055s , 4.021s.
ізоморфізми

@isomorphismes, як ти вимірював час? Якими засобами? До речі, я мушу сказати, ні. 1Моя улюблена.
Альберт

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

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

15
Цей 1.параметр спричинить великі болі при роботі з іменами папок, у яких є пробіли.
Шрікант Шарат

99

Я використовую:

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

Це створює єдиний стовпець без косої риски - корисно в сценаріях.

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


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

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

Коли я додаю це .bashrcяк псевдонім, як я додам '/'?
РНК

@RNA пізно відповісти, але для майбутніх людей: спробуйте втекти з зворотним нахилом? '\/'
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
jhnc

Це здається найбезпечнішим рішенням, оскільки пошук - це інструмент, який насправді зроблений для цього завдання. Перший результат - ./ для поточного каталогу можна виключити, перейшовши на grep -v '^ \ ./$'
siliconrockstar

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.- лс

GNU lsприйме клавішу "end of options" ( --).

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

Цей параметр є безпечним для кількох типів непарних імен файлів.


Я думаю, ви повинні замінити слово Безпечний на Надійне. Ваш пост змушує мене думати, що інші рішення "небезпечні" (вразливі чи експлуатовані.)
Амадо Мартінес

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
Ви припускаєте, що жоден каталог не має пробілів всередині їх імен.
Бенджамін R

7

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

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

2
абоls -d1 */ | tr -d "/"
ccpizza

Не потрібно викликати зовнішню команду:set -- */; printf "%s\n" "${@%/}"

Мені подобається рішення @wholanda. Моє трохи коротше рішення: (випробувано та працює): ls -d * / | sed 's | / || g'
klor

Також мати псевдонім lsdir корисно: alias lsdirs = "ls -d * / | sed 's | / || g'"
klor


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
Поясніть, будь ласка, що робить цей код і як він пов’язаний із цим питанням.
Кен ІН

1
вона виконує команду 'ls', а потім проходить цикл через тестовий вихід, якщо кожен є каталогом, і
лунає,

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

FYI, якщо ви хочете надрукувати всі файли в багаторядковому режимі, ви можете зробити ls -1друк кожного файлу в окремому рядку. file1 file2 file3


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

Відповісти на початкове запитання, */не має нічого спільного ls; це робиться оболонкою / Bash, в процесі, відомому як глобінг .

Саме тому 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

Найкоротша команда коли-небудь (насправді хак) для переліку лише каталогів. Введіть абсолютний шлях або відносний шлях до каталогу, що цікавить, і натисніть клавішу Enter, щоб увійти в каталог, що цікавить. Тепер введіть cdі натисніть клавішу вкладки . Зараз показані лише каталоги.

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

Наведена вище команда тепер повинна відображати лише папки на робочому столі . Найкоротший справді.


Це передбачає, що автозавершення ввімкнено, і може працювати не у всіх випадках. Крім того, якщо ви хотіли зробити щось із цим, як, наприклад, перетворити вихід на щось, воно не вийде. Але лише побачивши вихід, переконайтеся, що він працює швидко і легко.
lacostenycoder

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