Comment puis-je faire en sorte que «ls» affiche d'abord les fichiers dot tout en restant insensible à la casse?

21

Créez les fichiers suivants dans un répertoire.

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

Ma lscommande par défaut ignore la présence de points de tête, les confondant avec les autres fichiers.

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

Je peux changer LC_COLLATE pour mettre les dotfiles en premier.

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

Malheureusement, l'ordre de tri est sensible à la casse, c'est-à-dire Aet Bprécède aet b. Est - il possible d'imprimer dotfiles premier tout en restant insensible à la casse ( Aet aprecede Bet b)?

Modifier: tentative de modification de LC_COLLATE

Jusqu'à présent, aucune des réponses ne reproduit pleinement la fonctionnalité de lsfacilement. En théorie, je pourrais en encapsuler certains dans une fonction, mais cela devrait inclure un code détaillé sur (par exemple) comment travailler sans argument vs fournir un répertoire en tant qu'argument. Ou comment gérer un -dindicateur explicite .

Alternativement, je pensais qu'il pourrait y avoir une meilleure LC_COLLATEutilisation. Cependant, je n'arrive pas à faire fonctionner cela. J'utilise actuellement LC_COLLATE="en_AU.UTF-8". J'ai vérifié /usr/share/i18n/locales/en_AU(bien que je ne sois pas sûr que ce soit le bon fichier, car je ne vois aucune référence à UTF-8); J'ai trouvé ce qui suit.

LC_COLLATE
copy "iso14651_t1"
END LC_COLLATE

/usr/share/i18n/locales/iso14651_t1contient copy "iso14651_t1_common". Enfin, /usr/share/i18n/locales/iso14651_t1_commoncontient

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

J'ai supprimé cette ligne, exécuté sudo locale-genet redémarré mon ordinateur. Malheureusement, cela n'a rien changé.

Sparhawk
la source

Réponses:

11

OP était très proche de l'édition /usr/share/i18n/locales/iso14651_t1_common, mais l'astuce n'est pas de supprimer la ligne

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

mais plutôt de le modifier pour

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

Pourquoi cela fonctionne

Les IGNOREinstructions spécifient que le point final (c'est-à-dire la période ou le caractère <U002E>) sera ignoré lors de la commande alphabétique des mots. Pour que vos fichiers dot viennent en premier, passez IGNOREà un symbole d'assemblage qui précède tous les autres personnages. Les symboles d'assemblage sont définis par des lignes comme

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

et ils sont classés par l'apparence de la ligne

<something-inside-angle-brackets>

Dans ma copie de iso14651_t1_common, le symbole de classement en premier lieu est <RES-1>, qui apparaît à la ligne 3458. Si votre fichier est différent, utilisez le symbole de classement qui est commandé en premier.

Détails sur l'ordre des caractères avec LC_COLLATE

<U002E>a trois IGNOREdéclarations car les lettres peuvent être comparées plusieurs fois en cas d'égalité. Pour comprendre cela, considérez les minuscules aet les majuscules A(qui font partie d'un groupe de caractères qui sont en fait comparés quatre fois):

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

Le fait d'avoir plusieurs tours de comparaison permet de regrouper les fichiers commençant par "a" et "A" car les deux sont comparés comme <a>lors de la première passe, la lettre suivante déterminant l'ordre. Si toutes les lettres suivantes sont identiques (par exemple, a.txtet A.txt), la troisième passe passera en a.txtpremier car le symbole d'assemblage pour les lettres minuscules <MIN>apparaît sur la ligne 3467, avant le symbole d'assemblage pour les lettres majuscules <CAP>(ligne 3488).

Mettre en œuvre ce changement

Si vous souhaitez que la période vienne en premier à chaque fois qu'un programme commande des lettres à l'aide LC_COLLATE, vous pouvez modifier iso14651_t1_commoncomme décrit ci-dessus et reconstruire votre fichier d'emplacements. Mais si vous souhaitez effectuer cette modification uniquement vers lset sans accès root, vous pouvez copier les fichiers de paramètres régionaux d'origine dans un autre répertoire avant de les modifier.

Ce que j'ai fait

Ma langue par défaut est en_US, donc je copiais en_US, iso14651_t1et iso14651_t1_commonà $HOME/path/to/new/locales. Là , je fait le changement précité à iso14651_t1_commonet rebaptisés en_USà en_DOTFILE. Ensuite, j'ai compilé les paramètres régionaux en_DOTFILE avec

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

Pour remplacer l' lsordre par défaut , créez un script BASH appelé ls:

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

enregistrez-le quelque part qui apparaît avant /usr/binsur votre chemin et rendez-le exécutable avec chmod +x ls.

beandip
la source
bien sûr, vous devrez ajouter -a ou -A pour voir vos fichiers dot, mais à moins que vous ne vouliez toujours les voir, il est logique de le faire sur la ligne de commande, pas dans votre script BASH
beandip
Brillant! Merci, c'est parfait! Je viens de modifier le fichier appartenant à root, donc je n'ai pas testé votre script. Cependant, je pense que vous devez mettre des guillemets doubles autour de votre $@.
Sparhawk
bon appel - guillemets ajoutés
beandip
11

Vous pouvez utiliser à la place l'ordre de tri de la coque (qui ne peut donner l'ordre de classement de la locale; bash, AT & T ksh, yash, tcshet zshdonner les résultats escomptés, mkshet dash. Ne pas fishsemble donner un cas pour insensible , mais donne des résultats différents quand il y a des non-ASCII personnages):

ls -dUl -- .* *

Cela donne lsune liste explicite des fichiers (et répertoires) à lister et désactive lsle tri ( -Uqui est une extension GNU).

Il y a quelques mises en garde, selon le shell que vous utilisez.

  • Avec zsh, l' nomatchoption par défaut entraînera l'échec de la commande si le répertoire ne contient pas de fichiers cachés et non cachés; vous pouvez désactiver nomatchpour éviter cela, mais mieux serait de le faire à la set -o cshnullglobplace (et la commande à échouer uniquement si aucun des globes ne correspond comme dans les (t)cshpremiers ou les shells Unix).
  • Avec zsh, pdkshet son dérivé et fish, .*l'expansion de, n'inclut pas .et .., donc cela correspond ls -Al. Avec d'autres coquilles .et ..sont inclus pour qu'il corresponde ls -al. Dans ce dernier cas, vous devrez modifier les modèles de globalisation pour exclure .et ..( ls -dUl -- ..?* .[!.]* *).
  • Sauf dans fish, (t)cshou zsh, si l'un des modèles de globbing ne correspond à rien, lsproduira un message d'erreur; vous pouvez éviter cela en définissant l' nullgloboption (dans bashou zshau moins), ou en redirigeant stderrvers /dev/null( ls -dUl -- ..?* .[!.]* * 2>/dev/null). Si vous utilisez nullglob, faites attention au comportement potentiellement surprenant qui en résulte (voir Shell mangeant des caractères `? ' ). fishse comporte comme bashavec nomatchsauf que lorsqu'il est interactif, un message d'avertissement sera émis pour chaque glob qui n'a aucune correspondance.

(Merci à Stéphane Chazelas pour tous les retours!)

Stephen Kitt
la source
Notez que tous les shells ne trieront pas la liste en utilisant l'ordre de classement des paramètres régionaux. mkshet, dashpar exemple, ne triera pas en respectant la casse.
Stéphane Chazelas
1
Notez que -U(pour signifier non trié) est une extension GNU. Certaines autres lsimplémentations comme FreeBSD ont un -Umais ce n'est pas pour une liste non triée.
Stéphane Chazelas
Avec GNU ls, vous avez besoin --avant .*car cette implémentation accepte les options après les arguments (sauf si POSIXLY_CORRECT est dans l'environnement)
Stéphane Chazelas
Sournois (+1)! Cependant, je ne sais pas comment j'utiliserais cela facilement dans tous les cas, c'est-à-dire dans un alias ou une fonction. Par exemple, cela devrait changer si je veux spécifier un répertoire spécifique en lstant qu'argument.
Sparhawk
1
@PeterCordes [!.]est correct. Voir pubs.opengroup.org/onlinepubs/9699919799/utilities/… . Certains shells (la plupart?) Permettent ^comme synonyme de !globes de classe de caractères niés. En tout cas, je préfère .[!.] .??* *être légèrement plus compréhensible que.[!.]* ..?* *
jrw32982 supporte Monica
4

Vous pouvez simplement utiliser deux lscommandes distinctes :

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

Contrairement aux autres réponses jusqu'à présent, cette approche affiche les fichiers de points en évitant d'abord les entrées .et .., puis les entrées restantes dans ls l'ordre alphabétique.

Les réponses de @StephenKitt pourraient être améliorées pour obtenir le même résultat:

$ ls -dUl ..?* .[^.]* * 2>/dev/null
jlliagre
la source
+1 également, mais selon la réponse de StephenKitt, je ne sais pas comment j'utiliserais cela facilement dans tous les cas, c'est-à-dire dans un alias ou une fonction. Par exemple, cela devrait changer si je veux spécifier un répertoire spécifique lscomme argument. (FWIW J'utilise zsh, mais cela est utile pour les personnes bash, je suppose.)
Sparhawk
-2

Vous pouvez jouer avec les options de la commande ls . Essaye ça:

# ls -laXr

Où:

-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
la source
Désolé, cela ne semble pas faire ce que je veux. Le -Xdrapeau trie par l'extension après le ., ce qui est totalement différent. De plus, les fichiers sont classés par ordre alphabétique inversé. De plus, bien que les fichiers dot soient les premiers pour mon exemple, cela ne fonctionnera pas dans tous les cas (par exemple a.b c.d .a .c). Vous l'avez également utilisé à la -aplace de -A.
Sparhawk