Cara mengurutkan direktori pertama kemudian file dll ... saat menggunakan "ls" di Unix

91

Saya ingin menggunakan lsperintah untuk pertama menampilkan direktori dan kemudian file. Saya mencoba:

ls -la | sort -k 1

Tapi saya mendapat urutan yang salah.

atricapilla
sumber
itu karena -datang sebelumnya dketika menggunakansort
Nifle
4
Head unix head yang lama (yang berasal dari zaman pra-GUI) digunakan untuk mengubah nama folder menjadi huruf besar dan membuat nama file polos tanpa modal untuk mendapatkan hasil itu secara otomatis.
JRobert
Pertanyaan yang berguna! Mungkin sudah waktunya untuk mengubah jawaban yang diterima menjadi yang lebih sederhana dan tidak merusak warna terminal?
ippi
Cobals -lh --group-directories-first
Diogo

Jawaban:

28

Perintah berikut akan daftar direktori pertama, file biasa kedua, dan tautan ketiga.

ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep "^l"

Juga, akan sangat masuk akal untuk membuat alias untuk perintah ini untuk menyimpan penekanan tombol.

Sunting:

Jika Anda ingin direktori terlebih dahulu, dan kemudian semua yang bukan direktori kedua, gunakan ini:

ls -la | grep "^d" && ls -la | grep -v "^d"

sebelas81
sumber
1
Perintah ini tidak mencantumkan semua jika ada, misalnya, soket atau FIFO dalam folder
Studer
1
Versi yang diedit itu masih harus bekerja dengan tipe lain. Grep pertama mengatakan semua yang dimulai dengan 'd', dan yang kedua mengatakan semua yang tidak dimulai dengan 'd'. Tentunya semuanya dimulai dengan iklan atau tidak, kan?
Ry4an Brase
1
@ Mark - Mengapa tidak hanya melakukan: ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep -v -E "^d|^-|^total"?
FCTW
1
Untuk menjadikan @ FCTW's perintah OSX alias, tambahkan ini ke ~ / .profile Anda:alias la="ls -la | grep \"^d\" && ls -la | grep \"^-\" && ls -la | grep -E \"^d|^-\" -v | grep -v \"^total\""
aliteralmind
2
Saya telah menemukan notasi yang berfungsi lebih singkat: ls -la|grep ^d;ls -la|grep -v ^d(tanda kutip tidak diperlukan dan diganti &&dengan ;). Pilihan lain adalah untuk memperkenalkan variabel dan kemudian mengevaluasinya: a="ls -la|grep ^d";eval $a;eval $a -v. Dapat bermanfaat untuk menghindari pengulangan ketika lebih banyak opsi ditentukan untuk ls/ grep. Ada juga ls -la --group-directories-firstpilihan itu, namun imo tersingkat adalahls -la|sort
Steven Pribilinskiy
205

Saya sangat menyukai * nix dan suka melihat daya cipta yang masuk ke beberapa balasan ini ...

Milik saya hampir tidak seperti di GNU Linux:

alias ls='ls --color -h --group-directories-first'

Mengingat bahwa saya lebih nyaman dengan aplikasi linux CLI saya, saya juga cenderung memperbarui coreutils di OSX:

brew install coreutils
alias ls='/usr/local/bin/gls --color -h --group-directories-first'
jonathanserafini
sumber
6
sayangnya, ini tidak berfungsi pada terminal osx, karena - opsi tidak tersedia.
MEM
7
kembali cinta: Apakah itu sarkasme? Jika demikian, saya setuju.
allyourcode
4
Tujuan dari alias ls adalah untuk mendefinisikan elemen konfigurasi yang ingin saya gunakan 90% dari waktu. Kurang penekanan tombol untuk mencapai output yang diinginkan. Jika Anda pernah ingin memiliki output ls asli Anda selalu / bin / ls.
jonathanserafini
4
@MEM Jika Anda menggunakan OS X dan Anda menikmati menggunakan Terminal, Anda harus brew install bash Kemudian, ini akan berhasil! :)
Andrew Ashbacher
5
Pendapat saya: ini seharusnya jawaban yang diterima karena mencantumkan opsi baris perintah untuk mencapai tujuan dengan tepat, alih-alih kumpulan grep yang berbelit-belit, dll.
Ryan Griggs
17

Untuk pengguna Mac coreutils :

brew install coreutils

alias ls='ls --color -h --group-directories-first'

Dengan asumsi sistem Anda siap untuk homebrew :

Vadym Tyemirov
sumber
7
glsagak. Baik?
Paul Irish,
1
Ya, secara default. Anda juga dapat menggunakan coreutils secara default dengan PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH".
benesch
7

Ada hal-hal tertentu yang ingin saya lihat dalam daftar direktori, dan sejauh ini tidak ada jawaban di sini yang memenuhi semua persyaratan di bawah ini. Persyaratan saya untuk daftar direktori:

  1. Direktori dan file diurutkan berdasarkan abjad
  2. Direktori terdaftar terlebih dahulu
  3. Tautan simbolik (symlink) diurutkan seperti file
  4. Penyortiran tidak sensitif huruf besar-kecil
  5. Penyortiran mengabaikan semua karakter non-alfa terkemuka dalam nama file
  6. Cantuman termasuk jumlah total direktori (tidak termasuk ./dan ../), file, dan tautan
  7. Daftar termasuk ukuran total (penggunaan disk) dari direktori dan file
  8. Daftarnya harus terlihat sama di Linux dan Windows (Git Bash shell) - ini adalah yang paling sulit untuk dilakukan karena opsi yang nyaman seperti --group-directories-firsttidak bekerja di Git Bash untuk Windows

Setelah banyak peretasan, saya akhirnya menemukan satu-liner (meskipun garis yang sangat panjang ;-)) yang saya puas. Saya telah menugaskan ini ke alias bernama 'dir':

ls -dlF --color * .* | head -n2 && ls -AlF | LC_ALL=C grep "^d" | 
LC_ALL=C sort -k 9df && ls -AlF | LC_ALL=C grep "^[l-]" | 
LC_ALL=C sort -k 9df && echo -e `find -maxdepth 1 -type d ! -name . | 
wc -l` Dir\(s\) `du -hs | cut -f 1`\\t\\t`find -maxdepth 1 -type f | 
wc -l` File\(s\) `find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | 
tail -n 1 | cut -f 1`\\t\\t`find -maxdepth 1 -type l | wc -l` Link\(s\)

Agar lebih mudah dikelola, saya datang dengan perintah terpisah untuk menampilkan setiap segmen dari daftar direktori sesuai dengan keinginan saya, lalu menggabungkannya menggunakan &&operator.

  • ls -dlF --color * .* | head -n2- Ekstrak ./dan ../. Kami tidak ingin melewati ini sortkarena sudah dalam urutan yang benar, dan mengurutkannya dapat ../didaftarkan terlebih dahulu. The -dpilihan adalah untuk menyingkirkan "total" line; Saya ingin menambahkan -Funtuk memperlihatkan trailing slash untuk direktori (ini juga akan menandai symlink dengan "@" ketika Anda melakukan hal biasa ls -F).

  • ls -AlF | LC_ALL=C grep "^d" | LC_ALL=C sort -k 9df- Ekstrak direktori dan urutkan berdasarkan nama file (kolom ke-9), abaikan karakter non-alpha / spasi ( dopsi) dan huruf besar-kecil ( fopsi). The ls -Atidak termasuk opsi ./dan ../dari daftar karena kita sudah diekstrak dalam langkah sebelumnya. Saya cenderung untuk awalan semua grepdan sortperintah dengan LC_ALL=Creset lokal sehingga (1) output konsisten di seluruh shell Unix, dan (2) Anda kadang-kadang dapat melihat kinerja lebih cepat karena tidak lagi memiliki overhead karakter UTF-8 yang diatur ke berurusan dengan.

  • ls -AlF | LC_ALL=C grep "^[l-]" | LC_ALL=C sort -k 9df - Ini mirip dengan langkah di atas, tapi kali ini kami menyortir file dan symlink.

  • find -maxdepth 1 -type d ! -name . | wc -l- Dapatkan jumlah direktori, tidak termasuk ./dan ../.

  • find -maxdepth 1 -type f | wc -l - Dapatkan jumlah file.

  • find -maxdepth 1 -type l | wc -l - Dapatkan jumlah symlink.

  • du -hs | cut -f 1 - Ekstrak ukuran total semua subdirektori dalam format yang dapat dibaca manusia.

  • find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | tail -n 1 | cut -f 1 - Ekstrak ukuran total semua file dalam format yang dapat dibaca manusia.

Mari kita lihat diralias baru kita dalam aksi!

SEBELUM:

$ ls -alF
total 22
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/

SETELAH:

$ dir
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
      5 Dir(s) 2.8M           6 File(s) 31K           0 Link(s)

Satu kelemahan kecil adalah Anda tidak dapat memiliki daftar warna, karena karakter kontrol warna yang mengelilingi nama file membuat penyortiran terlalu tidak dapat diandalkan.


MEMPERBARUI

Alias ​​di atas sangat lambat ketika dijalankan dari direktori root dari sistem file yang dalam, jadi saya telah memperbarui ke perintah yang lebih sederhana tetapi jauh lebih performant ini:

ls -AFoqv --color --group-directories-first | tail -n +2 && find -maxdepth 1 -type f -printf '%s\n' | awk '{total+=$1} END {print total" bytes"}'

Output sampel:

$ dir
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .aws/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .gem/
drwxr-xr-x 1 Tom     0 Mar 29 19:32 .ssh/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .zbstudio/
drwxr-xr-x 1 Tom     0 Jun 16  2016 temp/
drwxr-xr-x 1 Tom     0 Jul 13  2016 vimfiles/
-rw-r--r-- 2 Tom   365 Mar 30 10:37 .aliases
-rw-r--r-- 1 Tom 16028 Mar 30 12:12 .bash_history
-rw-r--r-- 2 Tom  2807 Mar 30 12:12 .bash_profile
-rw-r--r-- 2 Tom  2177 Mar 29 23:24 .functions
-rw-r--r-- 1 Tom  1091 Mar 30 10:34 .gitconfig
-rw-r--r-- 1 Tom  8907 Mar 29 14:45 _viminfo
-rw-r--r-- 1 Tom  2444 Jul 13  2016 _vimrc
33819 bytes

Karena versi baru dari Git Bash untuk Windows mendukung --group-directories-first, kami tidak lagi harus kembali aktif sort. Meskipun alias baru tidak menampilkan informasi sebanyak alias sebelumnya, keuntungan kinerja lebih dari sepadan. Sebagai kegembiraan, Anda juga mendapatkan warna!

Terima kasih
sumber
Jawaban bagus! Tetapi ketika Anda berkata, "Setelah banyak peretasan, saya akhirnya menemukan satu kalimat ..." Ya, memang itu sebenarnya bukan "satu kalimat" dalam pengertian klasik. Mungkin masuk akal untuk mengambil logika itu dan membuatnya menjadi skrip shell mandiri dan menjalankannya atau menyebutnya sebagai alias.
JakeGould
@JakeGould Kamu cepat! Saya bahkan belum selesai membaca-baca jawaban saya dan Anda sudah selesai membacanya dan mengeluarkan komentar :). Ya, itu adalah kandidat utama untuk suatu fungsi, tapi saya terlalu malas pada saat itu, jadi masukkan saja ke file .bash_aliases saya. Di sisi lain, saya biasanya hanya menulis fungsi ketika saya tidak bisa melakukan sesuatu tanpa melewati parameter.
thdoan
@ 10basetom: Pertanyaan singkat: Bagaimana Anda mendapatkan warna berbeda untuk kolom di ls? Saya bisa mewarnai nama file dengan tipe file menggunakan ls --color, tapi saya tidak melihat cara untuk mendapatkan warna yang bermanfaat untuk kolom. Apa rahasianya
Pirx
@Pirx Saya percaya kolom diwarnai oleh sintaks Stack Exchange default menyoroti :-).
thdoan
Ya, sepertinya memang begitu, tapi ini ide yang bagus, dan solusinya ada di ;-)
Pirx
6

Anda punya beberapa pilihan, tergantung jika Anda ingin menjaga urutan abjad.

Anda bisa mencoba:

ls -al | sort -k1 -r

atau ini, untuk menjaga urutan alfabet untuk file dengan izin yang sama:

ls -al | sort -k1,1 -k9,9 -r

atau, seperti yang dikatakan sebelas81 (tetapi versi ini mencantumkan semuanya):

ls -la | grep "^ d" && ls -la | grep "^ -" && ls -al | grep -v "^ [d | -]"

Studer
sumber
1
Ini adalah solusi IMO yang lebih bagus. Menggunakan beberapa proses dan pipa untuk melakukan penyortiran alih-alih perpipaan untuk menyortir tampaknya agak mundur. Terutama sejak ls- al|sort -k1 -rbekerja. Yang hilang hanyalah -rbendera.
brice
@Brice Hal yang mengganggu saya tentang 'sort' adalah itu ./dan ../tidak akan menjadi dua baris pertama, dalam urutan itu. Selain itu, saya setuju bahwa ini adalah solusi yang lebih efisien.
thdoan
Bagaimana cara mewarnai output?
Danijel
5

Untuk jawaban delerious010 , saya akan menambahkan bahwa jika Anda ingin memesan gaya lama:

LANG=C ls -la --group-directories-first

(atau gunakan LC_ALL atau LANGUAGE atau LC_COLLATE setel ke "C").

Ini akan memberikan sesuatu yang mirip dengan:

.
..
DIR
Dir
dir
.hidden
123
UC_FILE
Uc_file
lc_file

Meskipun, jika saya ingat dengan benar, file dot tersembunyi awalnya muncul di depan direktori.

Dennis Williamson
sumber
2

Inilah fungsi untuk melakukan ini (bash atau zsh): Dan ... Saya tidak menyarankan ini adalah cara terbaik, tapi inilah yang saya buat dan saya gunakan saat ini:

berfungsi lss
{
    # Menampilkan daftar direktori dengan direktori di bagian atas.

    perintah ls --color = selalu $ @ | egrep '^ d | total'
    perintah ls --color = selalu $ @ | egrep -v '^ d | total';
}
SuperMagic
sumber
Hanya sebuah fyi ini tampaknya tidak berfungsi. Anda perlu menggunakan format daftar panjang ( ls -l) untuk memfilter menurut jenis file seperti itu. Juga, perintah ini akan memecah spasi (dalam bash). Anda perlu mengutip seperti ini: "$@"Jika Anda ingin menggunakan pendekatan ini, Anda dapat melakukan sesuatu seperti:function lss {local temp="$(command ls -l --color=always "$@")"; egrep --color=never '^d|total' <<<"$temp"; egrep --color=never -v '^d|total' <<<"$temp"}
Enam
2

ls -laX akan menampilkan direktori pertama dalam urutan abjad, tetapi akan mengacaukan daftar file.

Opsi panjang:

ls
    -l    # List
    --all
    -X    # Sort alphabetically by entry extension
Polisi
sumber
Ini hanya akan berfungsi jika Anda dapat benar-benar yakin bahwa setiap direktori tidak memiliki titik dalam namanya.
sebelas81
1

Cara lain ...

find . -d 1 -type d | ls -la | sort -r 

ATAU

ls -la | sort -r

ATAU

d=`find . -type d -d 1`;f=`find . -type f -d 1`; echo -e -DIRS- "\n$d\n" -FILES- "\n$f"
Eddie B
sumber
Apa yang dilakukan ini? Di mana Anda belajar mengetiknya?
Tamara Wijsman
Yah OS pilihan saya adalah Debian Linux. Versi paket utas gnu core Debian ls mendukung opsi --show-directories-first ... ketika saya mulai menggunakan OSX, saya hanya mengambil semua file bash dot saya dari kotak Debian dan meletakkannya di direktori rumah saya ... Saya punya banyak bash_aliases yang pecah jadi ... Saat itulah aku harus mencari beberapa solusi untuk aliasku ...
Eddie B
Yang pertama agak berlebihan ... Tidak ada alasan untuk menyortir direktori karena ini adalah urutan yang perlu kita modifikasi, bukan direktori ... the 'ls -la | sort -r 'adalah yang benar-benar berfungsi. Pada dasarnya ini menyatakan ... 1) A) Temukan. -d 1 -type d (Mulai dari direktori ini, cari satu kedalaman direktori dan cari direktori saja) B) ls -la (daftar file semua atribut) C) Urutkan secara terbalik 2) Lakukan sebagai 1) cukup drop the find. ..tidak diperlukan ... Saya sebenarnya lebih suka solusi Studers '... :-)
Eddie B
1

TL; DR

alias ls='ls -lhF --color'

list_sorted() {
    ls $* | grep "^d";
    ls $* | grep "^-";
    ls $* | grep -v -E "^d|^-|^total"
}

alias ll=list_sorted

Penjelasan

Saya menggunakan kombinasi solusi yang disediakan dalam jawaban dan komentar di sini.

Default ls

Pertama-tama, saya menimpa perilaku default untuk ls:

  • -l: Selalu tampilkan daftar sebagai daftar vertikal satu dimensi
  • -h: Tampilkan ukuran file dengan cara yang dapat dibaca manusia (mis. 4.0K bukannya 4096)
  • -F: Menampilkan indikator seperti garis miring untuk direktori
alias ls='ls -lhF --color'

Diperpanjang ll

Selanjutnya, saya menulis fungsi yang berisi logika pengurutan. Untuk setiap lssaya melewati setiap argumen yang semula disahkan untuk itu. Itu memungkinkan saya menggunakan alias dari direktori kerja yang berbeda dari yang ingin saya daftarkan (yaitu ls -a ~).

Juga, setiap panggilan ke lsdisalurkan ke grepperintah. Di sini, penyortiran terjadi. ls -l | grep "^d"misalnya hanya mendaftar direktori. Jika direktori harus didaftar terlebih dahulu, ini harus didahulukan dalam fungsi juga. Selanjutnya adalah file.

Terakhir, saya menunjukkan semua yang bukan direktori atau file (atau baris yang menunjukkan ukuran total isi direktori). Ini dilakukan dengan menangkap directoy, entri file biasa dan total entri dan kemudian membalikkan hasilnya melalui -vargumen.

list_sorted() {
    # List directories
    ls $* | grep "^d";
    # List regular files
    ls $* | grep "^-";
    # List everything else (e.g. symbolic links)
    ls $* | grep -v -E "^d|^-|^total"
}

Akhirnya, saya alias fungsi ke perintah baru. Khususnya saya tidak ingin menimpa lskalau-kalau fungsi saya melanggar beberapa skenario. Maka saya ingin dapat menggunakan ls. Atau, Anda selalu dapat menjalankan perintah yang tidak disebutkan lsdengan memohon \ls.

alias ll=list_sorted

Catatan

  • Saya menggunakan ;bukannya &&sebagai pembatas untuk perintah. Jika tidak, seseorang tidak dapat membuat daftar isi direktori yang tidak mengandung direktori (perintah ls pertama bernilai false, sehingga tidak memungkinkan eksekusi perintah berikutnya karena ditambah dengan &&. ;Hindari itu.)
kleinfreund
sumber
0

Ini adalah solusi skrip. Daftar hanya nama, tidak ada data inode, abjad, tidak peka huruf besar kecil, diformat ke dalam kolom. Meskipun itu baris-utama, bukan kolom utama seperti output default ls. Kolom menjadi sedikit berantakan jika ada nama file dengan> 26 karakter.

rm -f /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout

IFS=$'\n' read -d '' -r -a lines < /tmp/lsout

printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

Dan yang lainnya, dengan beberapa format tambahan.

rm -f /tmp/lsout
echo "  ---- Directories ---- " >> /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

rm -f /tmp/lsout
echo "  ------- Files ------- " >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

Output untuk yang terakhir terlihat seperti berikut, minus warna:

  ---- Directories ----   archive/                  bookmarks/              
Desktop/                  Documents/                Downloads/              
fff/                      health/                   Library/                
Movies/                   Music/                    Pictures/               
Public/                   rrf/                      scifi/            
testdir/                  testdir2/                                         
  ------- Files -------   @todo                     comedy            
delme                     lll                       maxims                  
schedule                  vtokens style

Hanya ingat untuk tidak alias atau mengubah perilaku default ls karena skrip ini menyebutnya.

Igorio
sumber