Daftar file yang diurutkan berdasarkan jumlah baris yang dikandungnya

32

Bagaimana saya bisa mendaftar jumlah baris dalam file /group/book/four/word, diurutkan berdasarkan jumlah baris yang dikandungnya?

ls -l perintah mencantumkannya tetapi tidak mengurutkannya

Ken R
sumber
1
Apakah Anda ingin file terdaftar berdasarkan jumlah baris, atau daftar jumlah baris dalam file atau keduanya? ls -ltidak memberikan jumlah baris. ls -lSmengurutkan file berdasarkan ukuran dengan beberapa lsimplementasi ( ukuran menjadi jumlah byte dalam konten).
Stéphane Chazelas

Jawaban:

34

Anda harus menggunakan perintah seperti ini:

find /group/book/four/word/ -type f -exec wc -l {} + | sort -rn
  • find: cari file di jalur yang Anda inginkan. Jika Anda tidak menginginkannya bersifat rekursif, dan findimplementasi Anda mendukungnya, Anda harus menambahkan -maxdepth 1sebelum -execopsi.
  • exec: memberi tahu perintah untuk mengeksekusi wc -lpada setiap file.
  • sort -rn: urutkan hasil secara numerik dalam urutan terbalik. Dari yang lebih besar ke yang lebih rendah.

(yang menganggap nama file tidak mengandung karakter baris baru).

jherran
sumber
Perhatikan bahwa ketika melewati lebih dari satu file (atau dengan beberapa implementasi, lebih dari satu file yang dapat dibaca), wcjuga akan mencetak satu totalbaris, jadi di sini Anda juga akan mendapatkan satu atau lebih "total" baris kecuali hanya ada satu file . Anda dapat mengirim ke grep /untuk menghapusnya.
Stéphane Chazelas
dibatalkan karena sortperintah
Francisco
bagaimana saya bisa memfilter untuk hanya menampilkan file dengan garis X minimum (kecuali X = 0 untuk contoh)?
Matriks
11

Non-rekursif

Mungkin versi paling sederhana jika Anda tidak perlu rekursif:

wc -l /group/book/four/word/*|sort -n

wcmenghitung baris (opsi -l) di setiap (tetapi tersembunyi) ( *) file di bawah /group/book/four/word/, dan sortmengurutkan hasilnya (melalui pipa |) secara numerik (opsi -n).

Rekursif

Seseorang membuat komentar untuk jawaban ini grep -rlc, sebelum menekannya. Memang grepmerupakan alternatif yang bagus, terutama jika Anda membutuhkan rekursif:

grep -rc '^' /group/book/four/word/|tr ':' ' '|sort -n -k2

akan menghitung (opsi -c) rekursif (opsi -r) baris yang cocok ( grep) '^'(yaitu, awal baris) dalam direktori /group/book/four/word/. Kemudian Anda harus mengganti titik dua dengan spasi, misalnya menggunakan tr, untuk membantu sort, yang ingin Anda urutkan secara numerik (opsi -n) pada kolom kedua (opsi -k2).

Pembaruan: Lihat komentar Stephane tentang batasan yang mungkin dan bagaimana Anda dapat benar-benar dihilangkan tr.

Skippy le Grand Gourou
sumber
3
grep -c .menghitung garis yang mengandung setidaknya satu karakter yang valid. Gunakan grep -c '^'untuk menghitung semua baris (juga akan menghitung karakter tambahan setelah baris baru terakhir dengan beberapa grepimplementasi). Perhatikan bahwa tidak semua grepimplementasi mendukung -rdan perilaku bervariasi di antara yang melakukannya. Anda tidak perlu menerjemahkan :s (titik dua, bukan titik koma) ke spasi sort. Gunakan saja -t:. Perhatikan bahwa asumsi bahwa nama file tidak mengandung :atau kosong atau karakter baris baru.
Stéphane Chazelas
1
Terima kasih telah memposting solusi non-rekursif Anda; Saya tidak tahu wcmemberikan semua yang berguna jika Anda melewati banyak jalur. Menggabungkan fungsi itu dengan wild card dan pipa ke sortbenar-benar bersih.
Qcom
7

Dengan zsh:

lines() REPLY=$(wc -l < $REPLY)
printf '%s\n' /group/book/four/word/*(.no+lines)

Kami mendefinisikan fungsi penyortiran baru linesyang menjawab dengan jumlah baris dalam file. Dan kami menggunakan o+lineskualifikasi glob yang bersama-sama dengan n(untuk jenis numerik), menentukan bagaimana hasil glob tersebut dipesan. ( .juga ditambahkan hanya untuk memeriksa file biasa).

Itu tidak membuat asumsi pada karakter apa nama file dapat berisi selain file tersembunyi (yang dimulai dengan .) dihilangkan. Tambahkan Dkualifikasi glob jika Anda menginginkannya juga.

Stéphane Chazelas
sumber
2
OP hanya ditandai bash...
l0b0
7
@ l0b0 itu tidak berarti bahwa orang berikutnya yang membutuhkan ini juga akan menjalankan bash.
terdon
4

Anda tidak menentukan apakah Anda juga ingin file dalam subdirektori dari /group/book/four/word. The findsolusi dalam jawaban jherran akan turun ke subdirektori. Jika itu tidak diinginkan, gunakan shell sebagai gantinya:

for file in ./*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

Jika nama file Anda dapat berisi baris baru, Anda dapat menggunakan sesuatu seperti:

for file in ./*; do 
    [ -f "$file" ] && 
        printf "%lu %s\0" "$(wc -l < "$file")" "$file"
done | sort -zn | tr '\0' '\n'

Akhirnya, jika Anda lakukan mau turun ke subdirektori, Anda dapat menggunakan ini dalam bash4 atau di atas:

shopt -s globstar
for file in ./**/*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

Perhatikan bahwa versi bashsebelum 4.3 mengikuti symlink ketika secara turun menurun pohon direktori (seperti zsh's atau tcsh' s ***/*).

Selain itu, semua solusi di atas akan mengabaikan file tersembunyi (yang namanya dimulai dengan a ., gunakan shopt -s dotglobuntuk memasukkannya) dan juga akan menyertakan jumlah baris tautan simbolik (yang findpendekatannya tidak akan).

terdon
sumber
Perhatikan bahwa perbedaan lain dari solusi jherran adalah bahwa Anda juga akan mempertimbangkan symlink ke file biasa ( -xtype fdi GNU find atau *(-.)di zsh) dan akan menghilangkan file tersembunyi.
Stéphane Chazelas
@ StéphaneChazelas terima kasih, diklarifikasi. Mengapa %ludi printf? Seingat saya, itu berarti desimal yang tidak ditandatangani, apakah itu benar-benar diperlukan? Mengapa tidak memperlakukan nomor sebagai string? Apakah itu membuat perbedaan?
terdon
2
Jika output wc kosong (misalnya karena file tidak dapat dibaca), maka itu akan berkembang menjadi 0bukan string kosong, yang sedikit lebih baik. Beberapa implementasi semacam bekerja dengan bilangan bulat yang tidak ditandatangani, beberapa dengan yang ditandatangani. %lukedengarannya seperti taruhan teraman, tetapi mungkin tidak masalah seolah-olah Anda memiliki 2^31garis, itu akan memakan waktu lama.
Stéphane Chazelas
1

Jika Anda ingin menginstal fdfile finder yang sangat cepat yang ditulis dalam Rust (Anda harus menginstalnya, itu bagus untuk dimiliki)

fd --type=file . | xargs wc -l | sort -n

Pada dasarnya fddaftar file, xargs akan meneruskan daftar file ke wc(singkatan dari jumlah kata tetapi melewati -l akan membuatnya menghitung baris) kemudian akhirnya diurutkan dari paling sedikit jumlah baris ke penggunaan terbesar sort -n.

JustGage
sumber