Jak sprawić, by najpierw sortował znaki podkreślenia?


20

Lubię móc nazywać pliki i katalogi prefiksem podkreślenia, jeśli chcę coś oddzielić od innych plików i katalogów na tym samym poziomie. Na przykład w systemach Windows i Mac poprzedzenie pliku znakiem podkreślenia sortuje go do góry, przed plikami rozpoczynającymi się od znaku alfanumerycznego.

Okazało się, że Google ma związek z LC_COLLATE i obecnymi ustawieniami narodowymi (en_US). W porządku, choć naprawdę nie rozumiem, dlaczego en_US nie sortuje zgodnie z oczekiwaniami.

Na podstawie ustawień regionalnych strony demonstracyjnej ICate Collate ustawienia en_US_POSIX z pewnością wydają się mieć porządek sortowania, którego szukam (musisz edytować przykładowe dane i dodać podkreślenia, aby je przetestować). Ale tak naprawdę nie widzę, jak zastosować to w mojej powłoce Linux.

Idealnie, chciałbym móc skonfigurować coś w mojej konfiguracji bash, aby zawsze ls najpierw sortował podkreślenia. Jak miałbym to zrobić?


Nie mogę reprodukować przy użyciu ICU Collate z ustawieniami domyślnymi ani z en_US_POSIX.txt poprzez „Pobierz reguły dla ustawień regionalnych”. Czy możesz wyjaśnić użyte ustawienia?
Mikel


@Mikel, korzystając z linku, który podałem powyżej, dodaj podkreślenia do danych testowych, a następnie prześlij, aby zobaczyć wyniki sortowania.
Tom Auger

Właśnie to zrobiłem, a ciągi zaczynające się od podkreślników są sortowane na środku, a nie na początku, tak jakby nie było tam podkreśleń.
Mikel

1
Powiązane pytanie, które dotyczy faktycznej zmiany definicji kolejności sortowania, to unix.stackexchange.com/questions/421908 .
JdeBP

Odpowiedzi:


5

Jeśli nie możesz lsposortować tak, jak chcesz, spróbuj rozszerzenia powłoki.

Wzorów nazw plików można używać do uruchamiania lsz listą plików, które powłoka już posortowała, z pominięciem używanej metody ls.

ls -lf _* [!_]*

Zakładając, że masz pliki

_a a _b b _c c

to jest jak bieganie

ls -lf _a _b _c a b c

Wyjaśnienie:

_* to wzór powłoki pasujący do dowolnej nazwy pliku rozpoczynającej się znakiem podkreślenia, rozwinięty w kolejności alfabetycznej.

[!_]*pasuje do dowolnej nazwy pliku, która nie zaczyna się od podkreślenia, rozwiniętej w kolejności alfabetycznej.

-fmówi, lsaby nie sortować, ponieważ powłoka już to zrobiła.

Więcej informacji: rozszerzenie nazwy pliku bash

Jeśli w bieżącym katalogu znajdują się katalogi, należy uruchomić następującą komendę, aby uniknąć wyświetlania list plików w katalogach:

ls -lfd _* [!_]*

7
Nawiasem mówiąc, DOS / Windows / OSX tak naprawdę nie umieszcza podkreślników przed innymi: sortują bez rozróżniania wielkości liter z podkreśleniem umieszczanym przed literami, ale niektóre inne znaki interpunkcyjne pojawiają się przed lub po podkreśleniu. Używanie, _aby pliki pojawiały się jako pierwsze, to hack specyficzny dla systemu operacyjnego; a uniksowa wersja tego hacka polega na rozpoczęciu nazwy pliku wielką literą: domyślną konwencją uniksową jest używanie tylko małych liter w nazwach plików.
Gilles 'SO - przestań być zły'

4
Lub zera; np 00README.
mattdm

1
@Gilles +1 za najlepszą praktykę uniksową dotyczącą używania wielkich liter w ważnych plikach, aby były pierwsze. Na koniec dnia, jeśli taka jest konwencja, prawdopodobnie najlepiej po prostu ją zaakceptuję, zamiast próbować zmusić system uniksowy do zachowywania się tak, jak robią to inne systemy operacyjne. Mogę stosować konwencje opracowane dla komputerów Mac lub Windows. Dzięki za świetną radę.
Tom Auger,

1
@TomAuger -fmówi, lsaby nie przeprowadzać własnego sortowania, więc wyświetla argumenty w kolejności, w jakiej zostały przekazane. Wynik każdego z firmy Shell wieloznaczne ekspansji _*i [!_]*jest leksykograficznie uporządkowany wykaz.
Gilles 'SO - przestań być zły'

1
@TomAuger Argumenty do lssortowania (w dwóch grupach: początkowej _, potem pozostałych), gdy są generowane przez powłokę. Uruchom, echo ls -lf _* [!_]*aby zobaczyć, co się stanie. -fFlaga mówi lsnie robić żadnych sortowania.
Gilles 'SO - przestań być zły'

16

Jeśli nie chcesz mieszać małych i wielkich liter, ustaw swój język na C, który przyjmuje znaki w kolejności numerycznej. _mieści się między wielkimi i małymi literami.

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

Ustawienia regionalne LC_MESSAGES(język komunikatów o błędach), LC_CTYPE(zestawy znaków) oraz LC_TIME(format daty i godziny) są bardzo przydatne. LC_COLLATEi LC_NUMERICzwykle są bardziej kłopotliwe niż są warte, nie zalecam ich ustawiania. Prawidłowe sortowanie leksykograficzne jest bardziej skomplikowane, niż LC_COLLATEpowinno się to określać, i może powodować różnego rodzaju dziwne zachowania, gdy używasz zakresów znaków w wyrażeniach regularnych. LC_NUMERICjest głównie kosmetyczny, z wyjątkiem sytuacji, gdy coś idzie strasznie nie tak, ponieważ jakiś program wygenerował liczbę z separatorem dziesiętnym innym niż ..


+1 Bardzo interesujące. Korzystając z tego formularza, tymczasowo ustawiasz zmienną środowiskową LC_COLLATE tylko dla jednego wystąpienia ls? Czy to prawda?
Tom Auger

1
Jakikolwiek sposób, aby podkreślenia pojawiały się PRZED dużymi literami?
Tom Auger

1
@TomAuger Tak, VAR=value cmdustawia VARsię valuetylko w środowisku cmdi nie dotyka wartości (lub braku wartości) w powłoce, w której ją uruchamiasz. Aby znak podkreślenia pojawiał się przed dużymi literami, musisz zdefiniować własne ustawienia regionalne. Jest to możliwe, ale niewygodne w użyciu, ponieważ przynajmniej w Linuksie biblioteka standardowa szuka tylko definicji ustawień narodowych /usr/lib/locale- nie ma ~/.localezmiennej środowiskowej ani zmiennej, w której można by umieścić swoje en_tomustawienie.
Gilles 'SO - przestań być zły'

@TomAuger Jeśli chodzi tylko o lspolecenie, skorzystaj z sugestii Mikela .
Gilles 'SO - przestań być zły'

2

Niestety, Linux używa glibc do informacji o lokalizacji, a nie do ICU, więc nie ma sposobu, aby zastosować to bezpośrednio do Linuksa, nie poświęcając wiele wysiłku ani na modernizację ICU na glibc, ani na uzupełnienie informacji o locale w glibc.


-4

Dodanie -fprzełącznika (bez sortowania) sprawiło, że pokazał mi się w ten sposób.

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

6
Tylko dlatego, że w ten sposób są przechowywane w systemie plików.
Ignacio Vazquez-Abrams

3
Przepraszamy, ale ta odpowiedź jest błędna. Test: touch 3 1 _1 _3 2 _2 && ls -flwyniki2 . 1 3 _2 _3 .. _1
Marco
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.