Daftar file yang diurutkan secara numerik


123

Saya memiliki banyak file dari log1hingga log164.

Saya mencoba untuk MENDAFTAR direktori (diurutkan) di terminal UNIX tetapi fungsi pengurutan hanya menyediakan format seperti ini:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

Yang saya inginkan adalah

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

Adakah saran yang bisa saya gunakan untuk melakukan ini?


8
Ini benar-benar pertanyaan pemrograman, dan tidak layak untuk dimigrasi hanya karena jawabannya melibatkan bahasa pemrograman shell rendahan !!!
tchrist

Jika Anda tahu sebelumnya bahwa mereka bernama log1.gzmelalui log164.gz, maka apa yang Anda bahkan perlu ls -1mereka untuk?
ruakh

1
@ruakh ls -1 menampilkan hasil dalam satu kolom daripada di

3
@ Rabiani: Saya tahu apa yang harus ls -1dilakukan: daftar nama file. Karena Anda sudah tahu nama file, saya tidak mengerti untuk apa Anda membutuhkannya. Tetapi karena Anda telah menerima jawaban Kevin, sekarang saya tahu: Anda tidak membutuhkannya. Yang lebih masuk akal. :-)
ruakh

Jawaban:


40

bashKawat gigi {},, akan menghitungnya dalam urutan:

for file in log{1..164}.gz; do
    process "$file"
done

267

Mengapa tidak menggunakan lsfitur bawaan untuk kasus khusus ini, yaitu

-v natural sort of (version) numbers within text

Sebagai contoh ls -1v log*


Solusi yang luar biasa, meskipun saya berharap ada solusi yang sama sederhana menggunakan sort, jika seseorang memiliki serangkaian string daripada direktori file
Hubro

23
Pada BSD / OSX pilihan ini adalah sesuatu yang lain: -v - Force unedited printing of non-graphic characters.
kenorb

Sayangnya opsi -v tidak tersedia di AIX (6.1)
bouvierr

6
Ini harus menjadi jawaban terbaik.
32r34wgf3e

1
untuk MacOS ini akan berfungsi, tidak dapat menemukan opsi seperti yang disebutkan, hanyals | sort -n
Ricky Levi

47

Dengan GNU ls (yaitu di Linux, Cygwin, atau sistem lain yang memiliki GNU ls khusus diinstal):

ls -v

Dalam zsh:

echo *(n)

Dalam cangkang lain:

echo log?.gz log??.gz log???.gz

Ganti echodengan printf '%s\n'jika Anda ingin setiap nama file pada baris terpisah.

Jika Anda menginginkan metadata file juga ( ls -l) dan Anda tidak memiliki GNU ls, Anda harus memanggil lssecara terpisah untuk setiap nama file atau grup nama file yang ingin Anda lihat dalam urutan leksikografis.

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

Untuk menghindari kesulitan ini, gunakan angka nol terkemuka di nama file Anda sehingga jenis leksikografis ramah-manusia ( log001.gz, dll.).


29

Meskipun solusinya ls -1vtentu yang paling baik dalam kasus ini, saya pikir itu baik untuk memiliki satu yang berfungsi sortseperti pada pertanyaan awal, karena ini juga berfungsi ketika input Anda tidak berasal ls. Dalam hal ini Anda dapat menggunakan:

ls -1 | sort -n -k1.4

The -npilihan memberitahu sort untuk mengurutkan numerik, dan -k 1.4menetapkan kunci semacam untuk field pertama (yang merupakan seluruh nama file dalam hal ini) mulai dari karakter ke-4 sampai dengan yang terakhir.


Dalam kasus saya, ls -1 | sort -n -k1.4tidak berfungsi. Ini memberikan yang tidak disortir pada awalnya hingga 4 karakter kemudian disortir setelah karakter ke-4. Saya menggunakan ls -1 |sort | sort -n -k1.4dan itu bekerja dengan sempurna.
Prabhu

3
@ Prabhu, sebagai gantinya, Anda bisa melakukannya sort -k1.1,1.3 -k1.4n. sortimplementasi tidak harus stabil sehingga pendekatan Anda tidak akan bekerja dengan semua implementasi. Lihat juga -Vopsi GNU dan FreeBSD sort.
Stéphane Chazelas

21

GNU sort(sebagaimana tersedia di Linux,) memiliki mode "versi sortir" yang menginterpretasikan angka-angka di dalam angka-bukan seperti yang Anda minta:

Dari man 1 sort:

    -V, --version-sort
           natural sort of (version) numbers within text

(Membuat file tes kosong ke daftar
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz:)

Kasing contoh Anda, menambahkan -Vopsi (atau --version-sort):

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz


3

Versi Solaris saya tidak mendukung ls -v(grrr). Dan solusi pengurutan yang disediakan di atas 1) membutuhkan pengetahuan tentang posisi digit dalam nama file, dan 2) tidak menangani hal-hal seperti nomor versi multi-bagian.

Pendekatan di bawah ini kompatibel dengan Solaris, tidak memerlukan pengetahuan awal tentang posisi digit, dan menangani nomor versi dengan 2, 3 atau 4 komponen (seperti: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). Ini juga digunakan sort -funtuk melipat huruf besar dan kecil bersama-sama, dan dengan benar menangani direktori yang dicampur dengan file:

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

Perhatikan bahwa versi ini membatasi komponen pertama menjadi satu digit.

Jika sistem operasi target Anda mendukung ls -v, itu jelas merupakan solusi yang unggul.


1

Solusi Perl:

ls log*.gz | perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; push @A, $_; END{ print sort { getnum $a <=> $b } @A}'

1
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz

1
Ini -t .berlebihan di sini.
Stéphane Chazelas

0

Ini berhasil untuk saya.

Saya punya file 1.jpg 2.jpg ... 18.jpg

$ echo *.jpg | tr -s ' ' '\n' | sort -n

sortsemakin bingung dengan lsoutput karena karakter warna yang tidak patut dicetak. Jika Anda mencoba ini:

ls -1 --color=none *.jpg | sort -n

ini akan bekerja dengan sempurna.

sortdapat mengabaikan karakter yang tidak diinginkan dengan -iopsi tetapi masih tidak berfungsi dan saya tidak tahu mengapa.

Tetapi Anda selalu dapat menghapus warna seperti ini dan sortakan bekerja:

ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

Saya berharap suatu hari sortakan memiliki opsi untuk ini.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.