Wie kann ich dafür sorgen, dass "ls" zuerst Punktdateien anzeigt, ohne die Groß- und Kleinschreibung zu beachten?

21

Erstellen Sie die folgenden Dateien in einem Verzeichnis.

$ touch .a .b a b A B 你好嗎

In meiner Standardreihenfolge lswerden führende Punkte ignoriert und mit den anderen Dateien vermischt.

$ ls -Al
total 0
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 A
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 B
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:06 你好嗎

Ich kann ändern LC_COLLATE , um die Punktedateien zuerst zu setzen.

$ LC_COLLATE=C ls -Al
total 0
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 A
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 B
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:06 你好嗎

Leider macht dies die Sortierreihenfolge zwischen Groß- und Kleinschreibung, dh Aund Bvor aund b. Gibt es eine Möglichkeit, zuerst Punktdateien zu drucken, ohne die Groß- und Kleinschreibung zu beachten ( Aund avor Bund b)?

Bearbeiten: Versuch, LC_COLLATE zu ändern

Keine der bisherigen Antworten gibt die Funktionalität von lseasy vollständig wieder . Es ist denkbar, dass ich einige davon in eine Funktion einbinden könnte, aber dies müsste einen detaillierten Code enthalten, der beschreibt, wie man ohne Argumente arbeitet, anstatt ein Verzeichnis als Argument anzugeben. Oder wie man mit einer expliziten -dFlagge umgeht.

Alternativ dachte ich, dass es vielleicht einen besseren geben könnte LC_COLLATE. Ich kann das jedoch nicht schaffen. Ich benutze gerade LC_COLLATE="en_AU.UTF-8". Ich habe es überprüft /usr/share/i18n/locales/en_AU(obwohl ich nicht sicher bin, ob dies die richtige Datei ist, da ich keinen Verweis darauf sehe UTF-8). Ich habe folgendes gefunden.

LC_COLLATE
copy "iso14651_t1"
END LC_COLLATE

/usr/share/i18n/locales/iso14651_t1enthält copy "iso14651_t1_common". Schließlich /usr/share/i18n/locales/iso14651_t1_commonenthält

 <U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .

Ich habe diese Zeile gelöscht sudo locale-gen, ausgeführt und meinen Computer neu gestartet. Daran hat sich leider nichts geändert.

Sparhawk
quelle

Antworten:

11

OP war sehr eng mit der Bearbeitung /usr/share/i18n/locales/iso14651_t1_common, aber der Trick besteht nicht darin, die Zeile zu löschen

<U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .

sondern um es zu ändern

<U002E> <RES-1>;IGNORE;IGNORE;<U002E> # 47 .

Warum funktioniert das?

Die IGNOREAnweisungen geben an, dass der Punkt (auch als Punkt oder Zeichen bezeichnet <U002E>) ignoriert wird, wenn Wörter alphabetisch sortiert werden. Damit Ihre Punktedateien an erster Stelle stehen, wechseln Sie IGNOREzu einem Sortiersymbol, das vor allen anderen Zeichen steht. Sortiersymbole werden durch Linien wie definiert

collating-symbol <something-inside-angle-brackets>

und sie sind nach dem Erscheinen der Linie geordnet

<something-inside-angle-brackets>

In meiner Kopie von iso14651_t1_commonsteht das Sortiersymbol für den ersten Platz <RES-1>in Zeile 3458. Wenn Sie eine andere Datei haben, verwenden Sie das Sortiersymbol, das zuerst bestellt wird.

Details zur Zeichenreihenfolge mit LC_COLLATE

<U002E>hat drei IGNOREAussagen, weil Buchstaben bei Gleichstand mehrfach verglichen werden können. Um dies zu verstehen, betrachten Sie Klein- aund Großbuchstaben A(die Teil einer Gruppe von Zeichen sind, die tatsächlich viermal verglichen werden):

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A

Durch mehrere Vergleichsrunden können Dateien, die mit "a" und "A" beginnen, zusammengefasst werden, da beide wie <a>beim ersten Durchgang verglichen werden und der nächste Buchstabe die Reihenfolge festlegt. Wenn alle folgenden Buchstaben gleich sind (z. B. a.txtund A.txt), wird der dritte Durchgang a.txtzuerst ausgeführt, da das Sortiersymbol für Kleinbuchstaben <MIN>in Zeile 3467 vor dem Sortiersymbol für Großbuchstaben <CAP>(Zeile 3488) angezeigt wird.

Implementierung dieser Änderung

Wenn Sie möchten, dass der Zeitraum bei jeder Bestellung von Briefen an erster Stelle steht LC_COLLATE, können Sie ihn iso14651_t1_commonwie oben beschrieben ändern und Ihre Standortdatei neu erstellen. Wenn Sie diese Änderung jedoch nur in lsund ohne Root-Zugriff vornehmen möchten, können Sie die ursprünglichen Gebietsschemadateien in ein anderes Verzeichnis kopieren, bevor Sie sie ändern .

Was ich getan habe

Meine Standard - Locale ist en_US, so dass ich kopiert en_US, iso14651_t1und iso14651_t1_commonzu $HOME/path/to/new/locales. Dort machte ich die oben genannte Änderung iso14651_t1_commonund umbenannt en_USzu en_DOTFILE. Als nächstes habe ich das Gebietsschema en_DOTFILE mit kompiliert

localedef -i en_DOTFILE -f UTF-8 -vc $HOME/path/to/new/locales/en_DOTFILE.UTF-8

Um die Standardreihenfolge zu ersetzen ls, erstellen Sie ein BASH-Skript mit dem Namen ls:

#!/bin/bash
LOCPATH=$HOME/path/to/new/locales LANG=en_DOTFILE.UTF-8 ls "$@"

Speichern Sie es an einer Stelle, die zuvor /usr/binauf Ihrem Pfad angezeigt wurde , und machen Sie es mit ausführbar chmod +x ls.

Bohnendip
quelle
Natürlich müssen Sie -a oder -A hinzufügen, um Ihre Punktedateien zu sehen, aber wenn Sie sie nicht immer sehen möchten, ist es sinnvoll, dies in der Befehlszeile zu tun, nicht in Ihrem BASH-Skript
beandip
Brillant! Danke, das ist perfekt! Ich habe gerade die Root-Datei geändert, sodass ich Ihr Skript nicht getestet habe. Ich denke jedoch, dass Sie doppelte Anführungszeichen um Ihre setzen müssen $@.
Sparhawk
Guter Anruf - doppelte Anführungszeichen hinzugefügt
Beandip
11

Sie können die Sortierreihenfolge der Shell verwenden , anstatt (was nicht die Sortierreihenfolge der locale beinhalten kann, bashAT & T ksh, yash, tcshund zshdie erwarteten Ergebnisse liefern, mkshund dash. Nicht fishscheinen einen Fall unempfindlich zu geben , aber unterschiedliche Ergebnisse liefern , wenn es nicht-ASCII Zeichen):

ls -dUl -- .* *

Dies gibt lseine explizite Liste der aufzulistenden Dateien (und Verzeichnisse) und deaktiviert lsdie Sortierung ( -Ueine GNU-Erweiterung).

Je nach verwendeter Shell gibt es einige Einschränkungen.

  • Mit zshder Standardoption nomatchschlägt der Befehl fehl, wenn das Verzeichnis nicht sowohl versteckte als auch nicht versteckte Dateien enthält. Sie könnten deaktivieren nomatch, um dies zu vermeiden, aber es wäre besser, dies set -o cshnullglobstattdessen zu tun (und den Befehl zum Fehlschlagen nur dann auszuführen, wenn keine der Globs wie in (t)cshoder frühen Unix-Shells übereinstimmt ).
  • Mit zsh, pdkshund seiner Ableitung und fish, .*schließt die Erweiterung .und nicht ein .., daher passt dies zusammen ls -Al. Mit anderen Muscheln .und ..sind so enthalten, dass es passt ls -al. Im letzteren Fall müssten Sie die Globbing-Muster ändern, um .und ..( ls -dUl -- ..?* .[!.]* *) auszuschließen .
  • Außer in fish, (t)cshoder zshwenn eines der Muster nicht mit irgendetwas übereinstimmt, lswird eine Fehlermeldung ausgegeben. Sie können dies entweder durch Setzen der nullglobOption (in bashoder zshzumindest) oder durch Umleiten stderrzu /dev/null( ls -dUl -- ..?* .[!.]* * 2>/dev/null) vermeiden . Achten Sie bei der Verwendung nullglobauf das möglicherweise überraschende Verhalten (siehe Shell, die Zeichen isst ). fishverhält sich wie bashmit der nomatchAusnahme, dass im interaktiven Modus eine Warnmeldung für jeden Glob ausgegeben wird, der keine Übereinstimmung aufweist.

( Vielen Dank an Stéphane Chazelas für all das Feedback!)

Stephen Kitt
quelle
Beachten Sie, dass nicht alle Shells die Liste in der Sortierreihenfolge des Gebietsschemas sortieren. mkshund dashzum Beispiel wird nicht ohne Rücksicht auf Groß- und Kleinschreibung sortiert.
Stéphane Chazelas
1
Beachten Sie, dass -U(um unsortiert zu bedeuten) eine GNU-Erweiterung ist. Einige andere lsImplementierungen wie FreeBSD haben ein, -Uaber es ist nicht für unsortierte Auflistung.
Stéphane Chazelas
Mit GNU lsmüssen Sie --vor, .*da diese Implementierung Optionen nach Argumenten akzeptiert (es sei denn, POSIXLY_CORRECT ist in der Umgebung)
Stéphane Chazelas
Hinterhältig (+1)! Ich bin mir jedoch nicht sicher, wie ich das in allen Fällen, z. B. in einem Alias ​​oder einer Funktion, problemlos verwenden würde. Zum Beispiel müsste es sich ändern, wenn ich ein bestimmtes Verzeichnis lsals Argument angeben möchte .
Sparhawk
1
@PeterCordes [!.]ist korrekt. Siehe pubs.opengroup.org/onlinepubs/9699919799/utilities/… . Einige (die meisten?) Shells erlauben ^als Synonym !in negierten Zeichenklassen Globs. In jedem Fall bevorzuge ich es .[!.] .??* *, etwas verständlicher zu sein als.[!.]* ..?* *
jrw32982 unterstützt Monica am
4

Sie können einfach zwei separate lsBefehle verwenden:

$ ls -dl ..?* .[^.]* 2>/dev/null ; ls -dl *
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 .a
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 .b
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 a
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 A
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 b
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 B
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 你好嗎

Im Gegensatz zu den bisherigen Antworten werden bei diesem Ansatz die Punktedateien zunächst ohne die Einträge .und ..und dann in ls alphabetischer Reihenfolge mit den verbleibenden Einträgen angezeigt .

@StephenKitt-Antworten können jedoch verbessert werden, um dasselbe Ergebnis zu erzielen:

$ ls -dUl ..?* .[^.]* * 2>/dev/null
jlliagre
quelle
+1 auch, aber gemäß StephenKitts Antwort bin ich mir nicht sicher, wie ich das in allen Fällen leicht verwenden würde, dh in einem Alias ​​oder einer Funktion. Zum Beispiel müsste es sich ändern, wenn ich ein bestimmtes Verzeichnis lsals Argument angeben möchte . (FWIW Ich verwende zsh, aber dies ist nützlich für Bash-Leute, nehme ich an.)
Sparhawk
-2

Sie können mit den ls- Befehlsoptionen spielen. Versuche dies:

# ls -laXr

Woher:

-l     use a long listing format
-a, --all
              do not ignore entries starting with .
-X     sort alphabetically by entry extension
-r, --reverse
              reverse order while sorting
Rodrigo Calvo
quelle
Entschuldigung, das scheint nicht zu tun, was ich will. Die -XFahne sortiert nach der Erweiterung nach der ., was völlig anders ist. Außerdem sind die Dateien in umgekehrter alphabetischer Reihenfolge. Auch wenn die Punktedateien für mein Beispiel die ersten sind, funktioniert dies nicht in allen Fällen (z a.b c.d .a .c. B. ). Außerdem hast du -astattdessen verwendet -A.
Sparhawk