Bagaimana cara membuat saya menyortir karakter garis bawah terlebih dahulu?

20

Saya suka bisa memberi nama file dan direktori dengan awalan garis bawah jika itu adalah sesuatu yang ingin saya pisahkan dari file dan direktori lain pada level yang sama. Pada Windows dan Mac, misalnya, mengawali file dengan garis bawah mengurutkannya ke atas, di depan file yang dimulai dengan karakter alfanumerik.

Googling saya telah menemukan bahwa itu ada hubungannya dengan LC_COLLATE dan lokal saya saat ini (en_US). Tidak apa-apa, meskipun saya benar-benar tidak mengerti mengapa en_US tidak seperti yang diharapkan.

Berdasarkan pengaturan situs demonstrasi ICU Collate lokal ke en_US_POSIX tentu saja tampaknya memiliki urutan semacam yang saya cari (Anda harus mengedit data sampel dan menambahkan beberapa garis bawah untuk mengujinya). Tapi saya tidak benar-benar melihat bagaimana menerapkan ini di shell Linux saya.

Idealnya, saya ingin dapat mengatur sesuatu dalam konfigurasi bash saya sehingga selalu mengurutkan garis bawah terlebih dahulu. Bagaimana saya bisa melakukan ini?

Tom Auger
sumber
Saya tidak dapat mereproduksi menggunakan ICU Collate dengan default atau dengan en_US_POSIX.txt melalui "Ambil aturan untuk lokal". Bisakah Anda menjelaskan pengaturan yang Anda gunakan?
Mikel
Pertanyaan serupa askubuntu.com/questions/47702/…
Mikel
@Mikel menggunakan tautan yang saya berikan di atas, tambahkan beberapa garis bawah pada data pengujian dan kemudian kirim untuk melihat hasil pengurutan.
Tom Auger
Itulah yang saya lakukan, dan string yang diawali dengan garis bawah disortir di tengah daripada di awal, seolah garis bawah itu tidak ada.
Mikel
1
Pertanyaan terkait, yang benar-benar berurusan dengan definisi definisi susunan, adalah unix.stackexchange.com/questions/421908 .
JdeBP

Jawaban:

5

Jika Anda tidak lsdapat mengurutkan seperti yang Anda inginkan, coba ekspansi shell.

Anda dapat menggunakan pola nama file untuk dijalankan lsdengan daftar file yang sudah diurutkan shell, melewati metode yang lsdigunakan.

ls -lf _* [!_]*

Dengan asumsi Anda memiliki file

_a a _b b _c c

ini seperti berlari

ls -lf _a _b _c a b c

Penjelasan:

_* adalah pola shell yang cocok dengan nama file yang dimulai dengan garis bawah, diperluas dalam urutan abjad.

[!_]*cocok dengan nama file apa pun yang tidak dimulai dengan garis bawah, diperluas dalam urutan alfabet.

-fmengatakan lsuntuk tidak mengurutkan, karena shell sudah melakukannya.

Informasi lebih lanjut: ekspansi nama file bash

Jika ada direktori di direktori saat ini Anda ingin menjalankan perintah seperti ini untuk menghindari daftar file dalam direktori:

ls -lfd _* [!_]*
Mikel
sumber
7
Omong-omong, DOS / Windows / OSX tidak benar-benar menempatkan garis bawah sebelum yang lain: mereka mengurutkan case-insensitive dengan garis bawah yang diletakkan di depan huruf, tetapi beberapa karakter tanda baca lainnya pergi sebelum atau setelah garis bawah. Menggunakan _untuk membuat file tampil pertama adalah hack khusus-OS; dan versi unix dari peretasan ini adalah memulai nama file dengan huruf besar: konvensi unix standar adalah dengan hanya menggunakan huruf kecil dalam nama file.
Gilles 'SANGAT berhenti menjadi jahat'
4
Atau nol; mis 00README.
mattdm
1
@Gilles +1 untuk praktik terbaik unix menggunakan caps pada file-file penting untuk membuatnya menjadi yang pertama. Pada akhirnya, jika itu adalah konvensi, mungkin yang terbaik saya hanya mengadopsi itu, daripada upaya untuk memaksa unix untuk berperilaku seperti OS lain sehingga saya dapat menggunakan konvensi yang dikembangkan untuk Mac atau Windows. Terima kasih atas tipnya.
Tom Auger
1
@TomAuger -fmengatakan lsuntuk tidak melakukan penyortiran sendiri, sehingga menampilkan argumen dalam urutan mereka berlalu. Hasil dari setiap ekspansi wildcard shell _*dan [!_]*merupakan daftar yang diurutkan secara leksikografis.
Gilles 'SANGAT berhenti menjadi jahat'
1
@ TomAuger Argumen untuk lsdiurutkan (dalam dua kelompok: yang dimulai dengan _, kemudian yang lain) ketika dihasilkan oleh shell. Berlari echo ls -lf _* [!_]*untuk melihat apa yang terjadi. The -fbendera mengatakan lsuntuk tidak melakukan penyortiran apapun.
Gilles 'SO- berhenti bersikap jahat'
16

Jika Anda tidak ingin mencampur huruf kecil dan besar, atur lokal Anda ke C, yang mengambil karakter dalam urutan numerik mereka. _jatuh di antara huruf besar dan kecil.

$ LC_COLLATE=C ls    
BAR  FOO  _score  _under  hello  world
$ LC_COLLATE=en_US ls                    
BAR  FOO  hello  _score  _under  world

Pengaturan lokal LC_MESSAGES(bahasa pesan kesalahan), LC_CTYPE(set karakter) dan LC_TIME(format tanggal dan waktu) sangat berguna. LC_COLLATEdan LC_NUMERICbiasanya lebih banyak masalah daripada nilainya, saya tidak menyarankan untuk mengaturnya. Penyortiran leksikografis yang tepat lebih rumit daripada LC_COLLATEyang seharusnya ditentukan, dan ini dapat menyebabkan semua jenis perilaku aneh ketika Anda menggunakan rentang karakter dalam ekspresi reguler. LC_NUMERICsebagian besar kosmetik, kecuali ketika ada sesuatu yang salah karena beberapa program menghasilkan angka dengan pemisah desimal selain ..

Gilles 'SANGAT berhenti menjadi jahat'
sumber
+1 Sangat menarik. Jadi, dengan menggunakan formulir ini, Anda sementara mengatur variabel lingkungan LC_COLLATE hanya untuk satu contoh ls? Apakah itu benar?
Tom Auger
1
Adakah cara untuk membuat garis bawah muncul SEBELUM huruf besar?
Tom Auger
1
@TomAuger Ya, VAR=value cmdset VARuntuk valuehanya di lingkungan cmddan tidak menyentuh nilai (atau tidak adanya nilai) di shell mana Anda menjalankannya. Untuk membuat garis bawah muncul sebelum huruf besar, Anda perlu menentukan pengaturan lokal Anda sendiri. Ini mungkin, tetapi canggung untuk digunakan, karena setidaknya di Linux, perpustakaan standar hanya mencari definisi lokal di /usr/lib/locale- tidak ada ~/.localeatau variabel lingkungan di mana Anda bisa meletakkan en_tompengaturan Anda .
Gilles 'SANGAT berhenti menjadi jahat'
@ TomAuger Jika ini hanya tentang lsperintah, pergi dengan saran Mikel .
Gilles 'SO- berhenti bersikap jahat'
2

Sayangnya Linux menggunakan glibc untuk info lokalnya, bukan ICU, jadi tidak ada cara untuk langsung menerapkan ini ke Linux tanpa mengeluarkan banyak upaya baik perkuatan ICU ke glibc atau menambah info lokal di glibc.

Ignacio Vazquez-Abrams
sumber
-4

Menambahkan -fsakelar (tanpa sortasi) membuatnya tampil seperti itu untuk saya.

man ls

[root@dusknoir ~/java/test]# ls -fl
total 0
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 _1
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 _2
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 _3
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 1
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 2
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 3
Tim
sumber
6
Hanya karena itulah cara mereka disimpan dalam sistem file.
Ignacio Vazquez-Abrams
3
Maaf, tapi jawaban ini jelas salah. Uji: touch 3 1 _1 _3 2 _2 && ls -flkeluaran2 . 1 3 _2 _3 .. _1
Marco