Come posso fare in modo che "ls" mostri prima i dotfile senza distinzione tra maiuscole e minuscole?


21

Creare i seguenti file in una directory.

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

Il mio lsordine predefinito ignora la presenza di punti iniziali, mescolandoli con gli altri file.

$ 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 你好嗎

Io posso cambiare LC_COLLATE per mettere al primo posto i dotfile.

$ 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 你好嗎

Sfortunatamente, questo fa distinzione tra maiuscole e minuscole, vale a dire Ae Bprecedono ae b. C'è un modo per stampare prima i dotfile rimanendo senza distinzione tra maiuscole e minuscole ( Ae aprecedendo Be b)?

Modifica: tentativo di modificare LC_COLLATE

Nessuna delle risposte finora replica completamente la funzionalità di lsfacilmente. Concepibilmente, potrei racchiuderne alcuni in una funzione, ma questo dovrebbe includere un codice dettagliato su (ad esempio) come lavorare senza argomenti vs. fornire una directory come argomento. O come gestire una -dbandiera esplicita .

In alternativa, ho pensato che forse potrebbe esserci un migliore LC_COLLATEda usare. Tuttavia, non riesco a farlo funzionare. Attualmente sto usando LC_COLLATE="en_AU.UTF-8". Ho controllato /usr/share/i18n/locales/en_AU(anche se non sono sicuro che questo sia il file giusto, in quanto non riesco a vedere alcun riferimento a UTF-8); Ho trovato quanto segue.

LC_COLLATE
copy "iso14651_t1"
END LC_COLLATE

/usr/share/i18n/locales/iso14651_t1contiene copy "iso14651_t1_common". Infine, /usr/share/i18n/locales/iso14651_t1_commoncontiene

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

Ho cancellato questa riga, eseguito sudo locale-gene riavviato il mio computer. Sfortunatamente, questo non ha cambiato nulla.

Risposte:


11

OP era molto vicino alla modifica /usr/share/i18n/locales/iso14651_t1_common, ma il trucco non è eliminare la linea

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

ma piuttosto modificarlo in

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

Perché questo funziona

Le IGNOREdichiarazioni specificano che il punto (punto o periodo <U002E>) verrà ignorato quando si ordinano le parole in ordine alfabetico. Per rendere i tuoi dotfile al primo posto, IGNOREpassa a un simbolo di confronto che precede tutti gli altri personaggi. I simboli di fascicolazione sono definiti da linee simili

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

e sono ordinati dall'aspetto della linea

<something-inside-angle-brackets>

Nella mia copia di iso14651_t1_common, il simbolo di fascicolazione al primo posto è <RES-1>, che appare sulla riga 3458. Se il file è diverso, utilizzare qualunque simbolo di fascicolazione sia ordinato per primo.

Dettagli sull'ordinamento dei personaggi con LC_COLLATE

<U002E>ha tre IGNOREaffermazioni perché le lettere possono essere confrontate più volte in caso di vincoli. Per capirlo, considera le lettere minuscole ae maiuscole A(che fanno parte di un gruppo di caratteri che vengono effettivamente confrontati quattro volte):

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

Avere più cicli di confronto consente di raggruppare i file che iniziano con "a" e "A" perché entrambi vengono confrontati come <a>durante il primo passaggio, con la lettera successiva che determina l'ordinamento. Se tutte le lettere seguenti sono uguali (ad es. a.txtE A.txt), il terzo passaggio verrà inserito per a.txtprimo perché il simbolo di fascicolazione per le lettere minuscole <MIN>appare sulla riga 3467, prima del simbolo di fascicolazione per le lettere maiuscole <CAP>(riga 3488).

Implementazione di questa modifica

Se vuoi che il periodo venga prima ogni volta che un programma ordina le lettere usando LC_COLLATE, puoi modificare iso14651_t1_commoncome descritto sopra e ricostruire il tuo file delle posizioni. Ma se si vuole fare questo cambiamento solo per lse senza accesso root, è possibile copiare i file di localizzazione originali in un'altra directory prima di modificarli.

Cosa ho fatto

Il mio locale di default è en_US, così ho copiato en_US, iso14651_t1e iso14651_t1_commonal $HOME/path/to/new/locales. Ci ho fatto il cambiamento di cui sopra per iso14651_t1_commone rinominato en_USa en_DOTFILE. Successivamente ho compilato la locale en_DOTFILE con

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

Per sostituire l' lsordinamento predefinito , crea uno script BASH chiamato ls:

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

salvalo da qualche parte che appare prima /usr/binsul tuo percorso e rendilo eseguibile con chmod +x ls.


ovviamente, dovrai aggiungere -a o -A per vedere i tuoi dotfile, ma a meno che tu non voglia sempre vederli, ha senso farlo dalla riga di comando, non nello script BASH
beandip

Brillante! Grazie, è perfetto! Ho appena modificato il file di proprietà di root, quindi non ho testato il tuo script. Tuttavia, penso che tu debba mettere doppie virgolette intorno al tuo $@.
Sparhawk,

buona chiamata - aggiunte doppie virgolette
beandip l'

11

È possibile utilizzare un sistema di classificazione della shell, invece (che non possono essere destinati ordine di collazione del locale, bash, AT & T ksh, yash, tcshe zshdare i risultati attesi, mkshe dash. Non fare fishsembra dare un caso di ordine insensibile ma dà risultati diversi quando ci sono non-ASCII personaggi):

ls -dUl -- .* *

Ciò fornisce lsun elenco esplicito di file (e directory) da elencare e disattiva lsl'ordinamento ( -Uche è un'estensione GNU).

Ci sono alcuni avvertimenti, a seconda della shell che stai usando.

  • Con zsh, l' nomatchopzione predefinita farà fallire il comando se la directory non contiene sia file nascosti che non nascosti; potresti disabilitarlo nomatchper evitarlo, ma sarebbe meglio fare set -o cshnullglobinvece (e il comando fallirebbe solo se nessuno dei globs corrispondesse come nelle precedenti (t)csho sulle shell Unix).
  • Con zsh, pdkshe la sua derivata e fish, .*l'espansione non include .e .., quindi questo corrisponde ls -Al. Con altre conchiglie .e ..sono inclusi in modo che corrisponda ls -al. In quest'ultimo caso, è necessario modificare gli schemi globbing per escludere .e ..( ls -dUl -- ..?* .[!.]* *).
  • Tranne in fish, (t)csho zsh, se uno qualsiasi dei modelli di globbing non corrisponde a nulla, lsprodurrà un messaggio di errore; puoi evitarlo impostando l' nullglobopzione (in basho zshalmeno) o reindirizzando stderra /dev/null( ls -dUl -- ..?* .[!.]* * 2>/dev/null). Se lo usi nullglob, fai attenzione al comportamento potenzialmente sorprendente che causa (vedi Shell che mangia i personaggi `?` ). fishsi comporta come bashcon nomatchla differenza che quando interattivo, un messaggio di avviso verrà emesso per ogni glob che non ha alcuna corrispondenza.

(Grazie a Stéphane Chazelas per tutto il feedback!)


Si noti che non tutte le shell ordineranno l'elenco usando l'ordine di confronto delle impostazioni locali. mkshe dashper esempio non ordinerà maiuscole e minuscole.
Stéphane Chazelas,

1
Si noti che -U(per indicare non ordinato) è un'estensione GNU. Alcune altre lsimplementazioni come FreeBSD hanno un -Uma non è per un elenco non ordinato.
Stéphane Chazelas,

Con GNU ls, è necessario --prima .*che l'implementazione accetti le opzioni dopo gli argomenti (a meno che POSIXLY_CORRECT sia nell'ambiente)
Stéphane Chazelas,

Subdolo (+1)! Tuttavia, non sono sicuro di come lo userei facilmente in tutti i casi, cioè in un alias o in una funzione. Ad esempio, dovrebbe cambiare se voglio specificare una directory specifica lscome argomento.
Sparhawk,

1
@PeterCordes [!.]è corretto. Vedi pubs.opengroup.org/onlinepubs/9699919799/utilities/… . Alcune conchiglie (la maggior parte?) Consentono ^come sinonimo di !globs di classe di caratteri negati. In ogni caso, preferisco .[!.] .??* *essere leggermente più comprensibile di.[!.]* ..?* *
jrw32982 supporta Monica

4

Potresti semplicemente usare due lscomandi separati :

$ 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 你好嗎

A differenza delle altre risposte finora, questo approccio visualizza prima i file di punti evitando le voci .e .., quindi le voci rimanenti in ls ordine alfabetico.

Le risposte di @StephenKitt potrebbero essere migliorate per ottenere lo stesso risultato:

$ ls -dUl ..?* .[^.]* * 2>/dev/null

Anche +1, ma secondo la risposta di StephenKitt, non sono sicuro di come lo userei facilmente in tutti i casi, cioè in un alias o in una funzione. Ad esempio, dovrebbe cambiare se voglio specificare una directory specifica lscome argomento. (FWIW sto usando zsh, ma questo è utile per le persone bash, suppongo.)
Sparhawk

-2

Puoi giocare con le opzioni di comando ls . Prova questo:

# ls -laXr

Dove:

-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

Scusa, non sembra fare quello che voglio. La -Xbandiera ordina per estensione dopo la ., che è totalmente diversa. Inoltre, i file sono in ordine alfabetico inverso. Inoltre, mentre i dotfile sono i primi per il mio esempio, non funzioneranno in tutti i casi (ad es a.b c.d .a .c.). Inoltre, hai usato -ainvece di -A.
Sparhawk,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.