Cara mengurutkan ukuran yang dapat dibaca manusia

11

Saya pada dasarnya mencari file kemudian mengurutkan berdasarkan ukuran. Script berfungsi jika saya tidak mengurutkan ukuran berdasarkan dapat dibaca manusia Tapi saya ingin ukurannya bisa dibaca manusia. Bagaimana saya bisa mengurutkan ukuran yang dapat dibaca manusia?

Sebagai contoh:

 ls -l | sort -k 5 -n | awk '{print $9 " " $5}'

Ini berfungsi seperti yang diharapkan, saya mendapatkan ukuran file saya dalam byte naik:

1.txt 1
test.txt 3
bash.sh* 573
DocGeneration.txt 1131
andres_stuff.txt 1465
Branches.xlsx 15087
foo 23735
bar 60566
2016_stuff.pdf 996850

Sekarang, saya ingin ukurannya bisa dibaca manusia, jadi saya menambahkan parameter -h ke ls, dan sekarang beberapa file rusak:

 ls -lh | sort -k 5 -n | awk '{print $9 " " $5}'
1.txt 1
DocGeneration.txt 1.2K
andres_stuff.txt 1.5K
test.txt 3
Branches.xlsx 15K
foo 24K
bar 60K
bash.sh* 573
2016_stuff.pdf 974K

tvo000
sumber
-k 5- bagaimana cara kerjanya?
ctrl-alt-delor
@ ctrl-alt-delor: Saya yakin ukurannya ada di kolom ke-5 dari lsoutput
jesse_b
2
Menggunakan dubukannya lsbisa menjadi ide yang bagus.
xenoid
... atau find's -printfdengan nya %pdan %sformatters (diikuti dengan ‘humanisation’ dari ukuran).
Stephen Kitt
@ Jesse_b kesalahan saya, saya hanya berasumsi bahwa data dalam pertanyaan (ditandai karena ini adalah apa yang saya dapatkan) adalah input yang diurutkan. Saya salah.
ctrl-alt-delor

Jawaban:

28

Mencoba sort -h k2

-h, --human-numeric-sort membandingkan angka yang dapat dibaca manusia (mis., 2K 1G)

Itu adalah bagian dari jenis gnu, jenis BSD, dan lainnya.

ctrl-alt-delor
sumber
5
Bukankah seharusnya parsing output lsharus dihindari?
3
@ Thomasz Tidak selalu. Jika ia memberikan output yang Anda butuhkan, menyalurkannya ke operasi pemformatan lain tidak terlalu berbahaya. Yang tidak seharusnya Anda lakukan adalah mengulangi keluaran dari ls, dan alih-alih menggunakan globbing file secara langsung. Globbing saja tidak akan bekerja di sini. Yang mengatakan, saya mungkin lebih suka duuntuk ini.
Bloodgain
1
@Bloodgain format ls tidak dijamin sama di seluruh sistem / ls binari, jadi menguraikannya dengan mudah dianggap mustahil.
D. Ben Knoble
1
Juga, nama file dengan spasi putih akan mengacaukan segalanya
D. Ben Knoble
1
@Bloodgain: files=(); for f in *; do [[ -L "$f" ]] && files+=("$f"); done; echo ${#files[@]}(Saya mungkin memiliki saklar tes symlink salah). Jika Anda tidak peduli dengan symlink files=(*); echo ${#files[@]},, yang menjadi portabel jika Anda menggunakan setdan tidak array.
D. Ben Knoble
29

lsmemiliki fungsi ini bawaan, gunakan -Sopsi dan urutkan dalam urutan terbalik:ls -lShr

       -r, --reverse
              reverse order while sorting

       -S     sort by file size, largest first
Mark McKinstry
sumber
1
-hbukan opsi standarls , tetapi harus dapat digunakan jika OP sudah memilikinya. Sisanya standar, dan itu pasti jawaban yang akan saya tulis.
Toby Speight
5
+1 Jangan main-main mengurai output ls.
David Richerby
Ini adalah jawaban terbaik, tetapi harus menyertakan info dalam komentar @ Toby: -Smungkin tidak tersedia untuk Anda ls. FWIW, -Sdidukung bahkan dengan perpustakaan Emacs ls-lisp.el, yang digunakan ketika OS tidak memiliki ls. Ini berfungsi di Emacs pada MS Windows, misalnya.
Drew
Ini harus menjadi jawaban yang diterima.
berhamburan
1
@Rew: Komentar Toby mengatakan bahwa -hmungkin tidak tersedia secara universal, tetapi OP sudah menggunakannya. -Sbenar - benar harus tersedia secara universal, karena itu ada di tautan POSIX yang disediakan Toby. Namun, beberapa toolkit non-POSIX memang ada di luar sana.
Kevin
5

Karena tidak ada shell spesifik yang disebutkan, inilah cara melakukan semuanya di zshshell:

ls -lhf **/*(.Lk-1024oL)

The **pola glob cocok seperti *tetapi di seluruh /di path, yaitu seperti pencarian rekursif akan melakukan.

The lsperintah akan memungkinkan ukuran yang dapat dibaca manusia dengan -h, dan daftar panjang format output dengan -l. The -fmenonaktifkan opsi pengurutan, sehingga lshanya akan daftar file dalam urutan mereka diberikan.

Urutan ini disusun oleh **/*(.Lk-1024oL)pola nama globbing sehingga file yang lebih kecil didaftar terlebih dahulu. The **/*bit cocok dengan setiap file dan direktori dalam direktori dan di bawah ini, tetapi (...)memodifikasi perilaku gumpal ini (itu adalah "kualifikasi segumpal").

Itu oLpada akhirnya yang memerintahkan ( o) nama berdasarkan ukuran file ( L, "panjang").

Di .awal membuat glob hanya cocok dengan file biasa (tidak ada direktori).

The Lk-1024file bit menyeleksi yang ukurannya kurang dari 1024 KB ( "panjang di KB kurang dari 1024").

Jika zshbukan shell interaktif utama Anda, maka Anda dapat menggunakannya

zsh -c 'ls -lf **/*(.Lk-1024oL)'

Gunakan setopt GLOB_DOTS(atau zsh -o GLOB_DOTS -c ...) untuk juga cocok dengan nama yang disembunyikan. ... atau tambahkan saja Dstring kualifikasi glob.


Memperluas di atas, dengan asumsi bahwa Anda ingin output 2-kolom dengan nama path dan ukuran yang dapat dibaca manusia, dan juga dengan asumsi bahwa Anda memiliki numfmtdari GNU coreutils,

zmodload -F zsh/stat b:zstat

for pathname in **/*(.Lk-1024oL); do
    printf '%s\t%s\n' "$pathname" "$(zstat +size "$pathname" | numfmt --to=iec)"
done

atau, lebih cepat,

paste <( printf '%s\n' **/*(.Lk-1024oL) ) \
      <( zstat -N +size **/*(.Lk-1024oL) | numfmt --to=iec )
Kusalananda
sumber
4

Jika Anda sorttidak memiliki -hopsi, Anda dapat menggunakan perintah awk (walaupun sangat panjang) seperti berikut:

find . -type f -size -1024k -exec ls -al {} \; | sort -k 5 -n | awk '{if ($5 > 1099511627776) {print $9,$5/1024/1024/1024/1024"T"} else if ($5 > 1073741824) {print $9,$5/1024/1024/1024"G"} else if ($5 > 1048576) {print $9,$5/1024/1024"M"} else if ($5 > 1024) {print $9,$5/1024"K"} else {print $9,$5"B"}}' | column -t

Ini akan mengurutkan output Anda dalam byte dan kemudian mengubahnya menjadi ukuran yang dapat dibaca manusia sesudahnya.

jesse_b
sumber
-1

Apakah ini akan berhasil?

ls -l | awk '{if ($5<=1024) {print}}' | sort -k 5 -n | awk '{print $9"\t"substr($5/1024,1,3)"k"} '| column -t

awkExp pertama akan mencari file yang kurang dari 1M dan yang kedua akan mengambil ukuran byte dari hasilnya dan mengubahnya menjadi KB dan mencetak 3 elemen pertama untuk memberikan ukuran yang dapat dibaca oleh manusia.

Vignesh SP
sumber
Itu tidak benar-benar menyelesaikan pertanyaan OP - hanya terlihat di direktori saat ini dan hanya akan mencetak file biasa. Juga akan dibandingkan dengan 1Kb, bukannya 1MB. Akhirnya kami mencari jawaban dengan beberapa penjelasan tentang mengapa kode ini bekerja.
grochmal
Buruk saya menambahkan apa yang dilakukannya.
Vignesh SP