Wie lasse ich ls zuerst Unterstriche sortieren?

20

Ich mag es, Dateien und Verzeichnisse mit einem Unterstreichungspräfix zu benennen, wenn es etwas ist, das ich von anderen Dateien und Verzeichnissen auf derselben Ebene trennen möchte. Wenn Sie beispielsweise unter Windows und Mac eine Datei mit einem Unterstrich voranstellen, wird diese nach oben sortiert, und zwar vor Dateien, die mit einem alphanumerischen Zeichen beginnen.

Es hat sich herausgestellt, dass mein Googeln mit LC_COLLATE und meinem aktuellen Gebietsschema (de_DE) zu tun hat. Das ist in Ordnung, obwohl ich wirklich nicht verstehe, warum en_US nicht wie erwartet sortiert.

Basierend auf der ICU Collate-Demonstrationssite, die das Gebietsschema auf "en_US_POSIX" setzt, scheint die von mir gesuchte Sortierreihenfolge zu stimmen (Sie müssen die Beispieldaten bearbeiten und einige Unterstriche hinzufügen, um sie zu testen). Aber ich sehe nicht wirklich, wie ich das in meiner Linux-Shell anwenden soll.

Im Idealfall möchte ich in meiner Bash-Konfiguration etwas einrichten können, damit ls immer zuerst die Unterstriche sortiert. Wie würde ich das machen?

Tom Auger
quelle
Ich kann nicht mit ICU Collate mit Standardeinstellungen oder mit en_US_POSIX.txt über "Abrufregeln für Gebietsschema" reproduzieren. Können Sie die von Ihnen verwendeten Einstellungen erklären?
Mikel
Ähnliche Frage askubuntu.com/questions/47702/…
Mikel
@Mikel über den Link, den ich oben angegeben habe, den Testdaten einige Unterstriche hinzufügen und dann übermitteln, um die Ergebnisse der Sortierung anzuzeigen.
Tom Auger
Genau das habe ich getan, und Zeichenfolgen, die mit Unterstrichen beginnen, werden eher in der Mitte als am Anfang sortiert, als ob die Unterstriche nicht vorhanden wären.
Mikel
1
Eine verwandte Frage, die sich mit der tatsächlichen Änderung der Sortierreihenfolgedefinition befasst, lautet unix.stackexchange.com/questions/421908 .
JdeBP,

Antworten:

5

Wenn Sie nicht lsso sortieren können, wie Sie möchten, versuchen Sie es mit einer Shell-Erweiterung.

Mithilfe von Dateinamenmustern können Sie lseine Liste von Dateien ausführen , die von der Shell unter Umgehung der verwendeten Methode bereits sortiert wurden ls.

ls -lf _* [!_]*

Vorausgesetzt, Sie haben die Dateien

_a a _b b _c c

das ist wie Laufen

ls -lf _a _b _c a b c

Erläuterung:

_* ist ein Shell-Muster, das jedem Dateinamen entspricht, der mit einem in alphabetischer Reihenfolge erweiterten Unterstrich beginnt.

[!_]*Stimmt mit jedem Dateinamen überein, der nicht mit einem in alphabetischer Reihenfolge erweiterten Unterstrich beginnt.

-fsagt lszu nicht sortieren, da die Shell bereits getan hat.

Weitere Informationen: Bash-Dateinamenerweiterung

Wenn sich im aktuellen Verzeichnis Verzeichnisse befinden, möchten Sie den Befehl folgendermaßen ausführen, um zu vermeiden, dass Dateien in den Verzeichnissen aufgelistet werden:

ls -lfd _* [!_]*
Mikel
quelle
7
Übrigens stellen DOS / Windows / OSX Unterstriche nicht wirklich vor alles andere: Sie sortieren ohne Berücksichtigung der Groß- und Kleinschreibung mit dem Unterstrich vor den Buchstaben, aber einige andere Interpunktionszeichen stehen vor oder nach dem Unterstrich. Das _erstmalige Anzeigen von Dateien ist ein betriebssystemspezifischer Hack. und die Unix-Version dieses Hacks soll den Dateinamen mit einem Großbuchstaben beginnen: Die Standard-Unix-Konvention besteht darin, in Dateinamen nur Kleinbuchstaben zu verwenden.
Gilles 'SO - hör auf böse zu sein'
4
Oder Nullen; zB 00README.
Mattdm
1
@Gilles +1 für die beste Unix-Praxis, bei wichtigen Dateien Großbuchstaben zu verwenden, damit sie an erster Stelle stehen. Letztendlich ist es wahrscheinlich das Beste, wenn ich das einfach übernehme, anstatt zu versuchen, Unix dazu zu zwingen, sich so zu verhalten, wie andere Betriebssysteme es tun. Daher kann ich Konventionen verwenden, die für Mac oder Windows entwickelt wurden. Danke für den tollen Tipp.
Tom Auger
1
@TomAuger -fweist lsan, keine eigene Sortierung vorzunehmen , und zeigt die Argumente in der Reihenfolge an, in der sie übergeben werden. Das Ergebnis jeder der Schale Wildcard Expansion _*und [!_]*eine lexikographisch sortiert Liste.
Gilles 'SO- hör auf böse zu sein'
1
@TomAuger Die Argumente lswerden sortiert (in zwei Gruppen: diejenigen, die mit beginnen _, dann die anderen), wenn sie von der Shell generiert werden. Lauf, um echo ls -lf _* [!_]*zu sehen, was passiert. Die -fFlagge sagt ls, dass keine Sortierung durchgeführt werden soll.
Gilles 'SO - hör auf böse zu sein'
16

Wenn Sie Kleinbuchstaben und Großbuchstaben nicht mischen möchten, setzen Sie Ihr Gebietsschema auf C, wobei die Zeichen in ihrer numerischen Reihenfolge angezeigt werden. _fällt zwischen Groß- und Kleinschreibung.

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

Die Gebietsschemaeinstellungen LC_MESSAGES(Sprache der Fehlermeldungen), LC_CTYPE(Zeichensätze) und LC_TIME(Datums- und Uhrzeitformat) sind sehr nützlich. LC_COLLATEund LC_NUMERICsind in der Regel mehr Mühe als sie wert sind, empfehle ich nicht, sie einzustellen. Eine korrekte lexikografische Sortierung ist komplizierter als vorgesehen LC_COLLATEund kann bei der Verwendung von Zeichenbereichen in regulären Ausdrücken zu verrückten Verhaltensweisen führen. LC_NUMERICist hauptsächlich kosmetisch, außer wenn etwas furchtbar schief geht, weil ein Programm eine Zahl mit einem anderen Dezimaltrennzeichen als erzeugt hat ..

Gilles 'SO - hör auf böse zu sein'
quelle
+1 Sehr interessant. Wenn Sie dieses Formular verwenden, setzen Sie die Umgebungsvariable LC_COLLATE vorübergehend nur für diese eine Instanz von ls? Ist das richtig?
Tom Auger
1
Gibt es eine Möglichkeit, die Unterstriche VOR den Großbuchstaben anzuzeigen?
Tom Auger
1
@TomAuger Ja, VAR=value cmdSätze VARzu valuenur in der Umgebung cmdund berührt nicht den Wert (oder das Fehlen des Wertes) in der Schale , wo Sie es laufen. Damit der Unterstrich vor Großbuchstaben angezeigt wird, müssen Sie Ihre eigenen Ländereinstellungen definieren. Dies ist möglich, aber umständlich zu verwenden, da die Standardbibliothek zumindest unter Linux nur nach Gebietsschemadefinitionen sucht /usr/lib/locale- es gibt keine ~/.localeoder Umgebungsvariable, in die Sie Ihre en_tomEinstellung einfügen könnten .
Gilles 'SO - hör auf böse zu sein'
@TomAuger Wenn es nur um den lsBefehl geht, folgen Sie dem Vorschlag von Mikel .
Gilles 'SO - hör auf böse zu sein'
2

Leider verwendet Linux glibc für seine Gebietsschemainformationen, nicht für die ICU. Daher gibt es keine Möglichkeit, diese direkt auf Linux anzuwenden, ohne viel Aufwand zu betreiben, entweder die ICU in glibc nachzurüsten oder die Gebietsschemainformationen in glibc zu ergänzen.

Ignacio Vazquez-Abrams
quelle
-4

Das Hinzufügen des -fSchalters (keine Sortierung) hat es mir gezeigt.

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
quelle
6
Nur weil sie so im Dateisystem gespeichert sind.
Ignacio Vazquez-Abrams
3
Entschuldigung, aber diese Antwort ist einfach falsch. Test: touch 3 1 _1 _3 2 _2 && ls -flAusgänge2 . 1 3 _2 _3 .. _1
Marco