Mendaftar hanya direktori menggunakan ls di Bash?

954

Perintah ini mencantumkan direktori di jalur saat ini: ls -d */

Apa sebenarnya yang dilakukan polanya */?

Dan bagaimana kita bisa memberikan path absolut dalam perintah di atas (mis. ls -d /home/alice/Documents) Untuk mendaftar hanya direktori di path itu?

Sibi
sumber
7
Lihat hasil edit untuk jawaban ini unix.stackexchange.com/a/75047/32647 menjelaskan apa yang -dsebenarnya dimaksud.
Evgeni Sergeev

Jawaban:

992

*/adalah pola yang cocok dengan semua subdirektori di direktori saat ini ( *akan cocok dengan semua file dan subdirektori; yang /membatasinya ke direktori). Demikian pula, untuk mendaftar semua subdirektori di bawah / home / alice / Documents, gunakanls -d /home/alice/Documents/*/

Gordon Davisson
sumber
88
Perhatikan bahwa */tidak akan cocok dengan folder tersembunyi. Untuk memasukkannya, tentukan secara eksplisit seperti mereka ls -d .*/ */, atau tetapkan dotglobopsi dalam Bash.
Gergő
1
@ytpillai Itu terjadi karena tidak ada subdirektori ke daftar. Anda mendapatkan kesalahan itu kapan saja Anda menggunakan lssesuatu yang tidak ada.
Gordon Davisson
1
Baiklah terima kasih, saya baru saja memeriksanya dan ternyata satu-satunya direktori adalah folder root.
ytpillai
1
@GordonDavisson Pesan kegagalan dapat dihindari dengan opsi bashshopt -s nullglob
4
Pengaturan @BinaryZebra nullglob akan menghindari pesan kesalahan, tetapi akan menyebabkan lebih banyak kebingungan: dengan set nullglob dan tanpa subdirektori, ls */akan diperluas menjadi adil ls, yang akan mencantumkan semua file di direktori saat ini. Saya cukup yakin bukan itu yang Anda inginkan dalam kasus itu.
Gordon Davisson
481

Empat cara untuk menyelesaikan ini, masing-masing dengan format output yang berbeda

1. Menggunakan echo

Contoh: echo */, echo */*/
Berikut adalah apa yang saya punya:

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

2. Menggunakan lshanya

Contoh: ls -d */
Inilah yang saya dapatkan:

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

Atau sebagai daftar (dengan info detail): ls -dl */

3. Menggunakan lsdangrep

Contoh: ls -l | grep "^d" Ini yang saya dapat:

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 (Tidak disarankan untuk nama file yang mengandung spasi)

Contoh: for i in $(ls -d */); do echo ${i%%/}; done
Ini yang saya dapat:

cs  
draft  
files  
hacks  
masters  
static

Jika Anda ingin memiliki '/' sebagai karakter akhir, perintahnya adalah: for i in $(ls -d */); do echo ${i}; done

cs/  
draft/  
files/  
hacks/  
masters/  
static/
Albert
sumber
2
NB. 3terasa lebih lambat daripada yang lain bagi saya. Dalam direktori saya menguji: 1.012s, 2.016s, 3 .055s , 4.021s.
isomorfisma
@ isomorfisma, bagaimana Anda mengukur waktu? Dengan apa yang berarti? Ngomong-ngomong, saya harus mengatakan, No. 1adalah favorit saya.
Albert
Albert, saya menggunakan time, fungsi Unix. /// Saya setuju, echo */lebih pintar dari ls -d */.
isomorfisma
9
Dua hal kecil yang harus Anda perhatikan. ls-l | grep "^ d" menyaring tautan simbolis ke direktori, sedangkan 'ls -d * /' menampilkannya. Juga, 'ls -d * /' gagal jika tidak ada direktori sama sekali di direktori target.
Zoran Pavlovic
15
The 1.pilihan akan menyebabkan nyeri utama ketika berhadapan dengan nama-nama folder yang memiliki ruang.
Shrikant Sharat
99

Saya menggunakan:

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

Ini membuat satu kolom tanpa garis miring - berguna dalam skrip.

Dua sen saya.

Thomas Altfather Bagus
sumber
18
The -1pilihan untuk lsakan menampilkan dalam format single-kolom juga, seperti dalam ls -1 -d */.
Kalin
3
@ user29020 Harus dicatat bahwa -1masih menampilkan garis miring untuk setiap entri.
Dennis
Ketika saya menambahkan ini .bashrcsebagai alias, bagaimana cara saya menambahkan '/'?
RNA
@RNA terlambat menjawab, tetapi untuk orang-orang masa depan: coba melarikan diri dengan backslash? '\/'
Caek
1
Hancur jika ada garis miring. Ini hanya menghilangkan garis miring:| sed -e 's-/$--'
Victor Sergienko
62

Untuk semua folder tanpa subfolder:

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

Untuk semua folder dengan subfolder:

find /home/alice/Documents -type d
at3m
sumber
2
Untuk mencocokkan pertanyaan (tetapi termasuk dotfiles), yang pertama harus: find /home/alice/Documents -maxdepth 1 -mindepth 1 -type djika tidak Anda sertakan /home/alice/Documentssendiri. Untuk memasukkan symlink ke direktori, -L
awali
Ini sepertinya solusi paling jernih, karena find adalah alat yang sebenarnya dibuat untuk tugas ini. Anda dapat mengecualikan hasil pertama - ./ untuk direktori saat ini - dengan
mem
38

4 (lebih banyak) Opsi yang Dapat Diandalkan.

Tanda bintang yang tidak dikutip *akan ditafsirkan sebagai pola (gumpalan) oleh shell.
Shell akan menggunakannya dalam ekspansi pathname.
Ini kemudian akan menghasilkan daftar nama file yang cocok dengan pola tersebut.
Tanda bintang sederhana akan cocok dengan semua nama file di PWD (direktori kerja saat ini).
Pola yang lebih kompleks karena */akan cocok dengan semua nama file yang berakhiran /.
Jadi, semua direktori. Itu sebabnya perintah:

1.- gema.

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

akan diperluas (oleh shell) ke echosemua direktori di PWD.


Untuk menguji ini: Buat direktori ( mkdir) bernama seperti test-dir, dan cdke dalamnya:

mkdir test-dir; cd test-dir

Buat beberapa direktori:

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:

Perintah echo ./*/akan tetap dapat diandalkan bahkan dengan file bernama aneh:

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

Tetapi spasi dalam nama file membuat membaca sedikit membingungkan.


Jika alih-alih echo, kami menggunakan ls, shell masih memperluas daftar nama file. Shell adalah alasan untuk mendapatkan daftar direktori di PWD. The -dpilihan untuk lsmerek itu daftar entri direktori ini bukan isi dari setiap direktori (seperti yang disajikan secara default).

ls -d */

Namun, perintah ini (agak) kurang dapat diandalkan. Ini akan gagal dengan file aneh bernama di atas. Ini akan tersedak dengan beberapa nama. Anda perlu menghapus satu per satu sampai Anda menemukan yang bermasalah.

2.-

GNU lsakan menerima kunci "akhir opsi" ( --).

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

3.-printf

Untuk membuat daftar setiap direktori di barisnya sendiri (dalam satu kolom, mirip dengan ls -1), gunakan:

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

Dan, yang lebih baik lagi, kita dapat menghapus trailing /:

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

Upaya seperti ini:

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

Akan gagal pada:

  • beberapa nama ( ls -d */) seperti yang sudah ditunjukkan di atas.
  • akan dipengaruhi oleh nilai IFS.
  • akan membagi nama pada spasi dan tab (dengan default IFS).
  • setiap baris baru dalam nama akan memulai perintah gema baru.

4.- Fungsi

Akhirnya, menggunakan daftar argumen di dalam suatu fungsi tidak akan mempengaruhi daftar argumen dari shell yang sedang berjalan. Secara sederhana:

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

menyajikan daftar ini:

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

Opsi ini aman dengan beberapa jenis nama file aneh.


sumber
Saya pikir Anda harus mengganti kata Safe dengan Reliable. Pos Anda membuat saya berpikir bahwa solusi lain 'tidak aman' (rentan atau dapat dieksploitasi.)
Amado Martinez
1
@AmadoMartinez Dilakukan umum / aman / dapat diandalkan /. Lebih baik?
21

The treePerintah ini juga cukup berguna di sini. Secara default akan menampilkan semua file dan direktori ke kedalaman penuh, dengan beberapa karakter ascii menampilkan pohon direktori.

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

Tetapi jika kami hanya ingin mendapatkan direktori, tanpa pohon ascii, dan dengan path lengkap dari direktori saat ini, Anda dapat melakukannya:

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

Argumennya adalah:

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

Dan jika Anda menginginkan path absolut, Anda bisa mulai dengan menentukan path lengkap ke direktori saat ini:

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

Dan untuk membatasi jumlah subdirektori, Anda dapat mengatur level maksimum subdirektori dengan -L level, misalnya:

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

Lebih banyak argumen dapat dilihat dengan pohon manusia

Hamish Downer
sumber
15

Jika Anda bertanya-tanya mengapa output dari 'ls -d * /' memberi Anda dua garis miring, seperti:

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

mungkin karena suatu tempat file konfigurasi shell atau sesi Anda alias perintah ls ke versi ls yang menyertakan flag -F. Bendera itu menambahkan karakter ke setiap nama keluaran (itu bukan file biasa) yang menunjukkan jenisnya. Jadi satu garis miring adalah dari pencocokan pola '* /', dan garis miring lainnya adalah indikator jenis yang ditambahkan.

Untuk menghilangkan masalah ini, Anda tentu saja dapat mendefinisikan alias berbeda untuk ls. Namun, untuk sementara tidak memanggil alias, Anda bisa menambahkan perintah dengan backslash:

\ ls -d * /

gwideman
sumber
11

Saya hanya menambahkan ini ke .bashrcfile saya (Anda juga bisa mengetiknya di baris perintah jika Anda hanya perlu / menginginkannya untuk satu sesi)

alias lsd='ls -ld */'

maka lsd akan menghasilkan hasil yang diinginkan.

bintang tamu
sumber
Tidak bisakah Anda menggunakan saja? ls-l path | grep dr
jrobertsz66
5
"Maka lsd akan menghasilkan hasil yang diinginkan." Saya tertawa
fbafelipe
1
Dalam pengalaman saya, itu membuahkan hasil.
Todd
Saya menggunakan 'lad' (daftar semua direktori), dan saya juga memasukkan '. * /' Untuk memasukkan direktori tersembunyi juga. Tentu saja, sindiran itu tidak hilang pada saya juga.
DryLabRebel
11

lsSolusi aktual , termasuk symlink ke direktori

Banyak jawaban di sini yang tidak benar-benar digunakan ls (atau hanya menggunakannya dalam pengertian sepele ls -d, saat menggunakan wildcard untuk pencocokan subdirektori yang sebenarnya. lsSolusi yang benar berguna, karena memungkinkan penggunaan lsopsi untuk mengurutkan pesanan, dll.

Tidak termasuk symlink

Satu solusi menggunakan lstelah diberikan, tetapi ia melakukan sesuatu yang berbeda dari solusi lain di dalamnya tidak termasuk symlink ke direktori:

ls -l | grep '^d'

(mungkin disalurkan melalui sedatauawk mengirim untuk mengisolasi nama file)

Termasuk symlink

Dalam kasus (mungkin lebih umum) yang menyertakan symlink ke direktori, kita dapat menggunakan -popsi ls, yang membuatnya menambahkan karakter slash ke nama direktori (termasuk yang symlink):

ls -1p | grep '/$'

atau, menghilangkan garis miring:

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

Kami dapat menambahkan opsi lssesuai kebutuhan (jika daftar panjang digunakan, -1tidak lagi diperlukan).

catatan: jika kita ingin membuntuti garis miring, tetapi tidak ingin mereka disorot grep, kita dapat menghapus sorotan dengan membuat bagian yang cocok dari baris itu kosong:

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

Jika direktori tersembunyi tidak perlu dicantumkan, saya menawarkan:

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

Dan jika direktori tersembunyi perlu dicantumkan, gunakan:

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

ATAU

find -maxdepth 1 -type d | awk -F"./" '{print $2}'
Pelajar PHP
sumber
Jika Anda perlu tahu lebih banyak tentang awk, silakan lihat jawaban
PHP Learner
Dibandingkan dengan jawaban lain, opsi pertama "ls .. | grep ... | awk" tampaknya scripting yang berlebihan.
Lars Nordin
1
Anda mengasumsikan tidak ada direktori yang memiliki spasi putih di dalam nama mereka.
Benjamin R
7

untuk menampilkan daftar folder tanpa /

ls -d */|sed 's|[/]||g'
wholanda
sumber
2
atauls -d1 */ | tr -d "/"
ccpizza
Tidak perlu memanggil perintah eksternal:set -- */; printf "%s\n" "${@%/}"
Saya suka solusi @whanda. Solusi saya yang sedikit lebih pendek adalah (diuji & berfungsi): ls -d * / | sed 's | / || g'
klor
Juga memiliki alias lsdir berguna: alias lsdirs = "ls -d * / | sed 's | / || g'"
klor
6

Inilah yang saya gunakan

ls -d1 /Directory/Path/*;

Larangan
sumber
Ini sebenarnya solusi yang cukup bagus untuk menampilkannya baris demi baris.
Nikolay Frick
Itu tidak akan mencantumkan direktori saja. Anda harus menambahkan garis miring:ls -d1 /Directory/Path/*/
Skippy le Grand Gourou
6

Untuk daftar direktori saja :

ls -l | grep ^d

hanya untuk daftar file :

ls -l | grep -v ^d 

atau juga Anda dapat melakukan sebagai: ls -ld * /

Vijay Gawas
sumber
4

Uji apakah item tersebut adalah direktori dengan test -d:

for i in $(ls); do test -d $i && echo $i ; done
kapal laut
sumber
1
Tolong jelaskan apa yang kode ini lakukan, dan bagaimana kaitannya dengan pertanyaan itu.
Ken YN
1
itu menjalankan perintah 'ls' kemudian loop melalui output pengujian-ing jika masing-masing adalah direktori dan bergema jika itu .. berfungsi tetapi ada cara yang lebih baik
ShoeLace
3

*/ adalah pola nama file yang cocok dengan direktori di direktori saat ini.

Untuk daftar direktori saja, saya suka fungsi ini:

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

Masukkan ke dalam .bashrc Anda.

Contoh penggunaan:

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

CATATAN: itu akan rusak jika Anda menggunakan -iopsi. Ini adalah perbaikan untuk itu:

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

FYI, jika Anda ingin mencetak semua file dalam multi-line, Anda dapat melakukan ls -1yang akan mencetak setiap file dalam baris terpisah. file1 file2 file3

warfreak92
sumber
3

Daftar sederhana dari direktori saat ini, itu akan menjadi:

ls -1d ./*/

Apakah Anda ingin disortir dan dibersihkan?

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

Ingat: huruf kapital memiliki perilaku berbeda dalam pengurutan

PYK
sumber
3

Coba yang ini. Ini bekerja untuk semua distro linux.

ls -ltr | grep drw
Raj RD
sumber
4
ls -l | grep '^d' | awk '{print $9}'
DW1
2

One-liner ke daftar direktori hanya dari "sini".

Dengan jumlah file.

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

Saya sebagian terpecahkan dengan:

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

Nah, ini dikurangi untuk saya, bagian walikota :)

inukaze
sumber
2

Menambahkan untuk menjadikannya lingkaran penuh, untuk mengambil jalur setiap folder, gunakan kombinasi jawaban Albert dan Gordans yang seharusnya cukup berguna.

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

Keluaran:

/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/
BilliAm
sumber
2

Menggunakan Perl:

ls | perl -nle 'print if -d;'
Paul-Gerhard Woolcock
sumber
1

Inilah yang saya gunakan untuk mendaftar hanya nama direktori:

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

Untuk menjawab pertanyaan awal, */tidak ada hubungannya dengan lsper se; itu dilakukan oleh shell / Bash, dalam proses yang dikenal sebagai globbing .

Inilah sebabnya echo */dan ls -d */menampilkan elemen yang sama. ( -dBendera membuat lskeluaran nama direktori dan bukan isi direktori.)

flow2k
sumber
1

Berikut adalah variasi menggunakan pohon yang menampilkan nama direktori hanya pada baris terpisah, ya itu jelek tapi hei, itu berfungsi.

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

atau dengan awk

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

Ini mungkin lebih baik namun dan akan mempertahankan /nama direktori setelah.

ls -l | grep "^d" | awk '{print $9}'
lacostenycoder
sumber
ini terlihat seperti bahasa Korea!
Paschalis
0
file *|grep directory

O / P (Di mesin saya) -

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

Output di atas dapat lebih disempurnakan dengan menggunakan cut.

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
AVS
sumber
0

Perintah terpendek yang pernah (sebenarnya peretasan) untuk daftar direktori saja. Ketikkan jalur absolut atau jalur relatif dari direktori yang diminati dan tekan enter untuk masuk ke direktori yang diminati. Sekarang ketik cddan tekan tombol tab . Hanya direktori yang ditampilkan sekarang.

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

Perintah di atas seharusnya sekarang hanya menampilkan folder di Desktop . Memang terpendek.

Prometheus
sumber
Ini mengasumsikan pelengkapan otomatis diaktifkan dan mungkin tidak berfungsi dalam semua kasus. Juga, jika Anda ingin melakukan sesuatu dengan ini seperti pipa keluaran menjadi sesuatu, itu tidak akan berhasil. Tapi untuk sekedar melihat output, pasti bekerja cepat dan mudah.
lacostenycoder
Sempurna! Saya menghapus "." Dan kemudian berhasil
user2060451