Comment trier les premiers répertoires puis les fichiers etc… quand on utilise “ls” dans Unix


91

Je voudrais utiliser la lscommande pour afficher d’abord les répertoires, puis les fichiers. J'ai essayé:

ls -la | sort -k 1

Mais j'ai un mauvais ordre.


c'est parce qu'il -vient avant d' dutilisersort
Nifle

4
Les anciennes têtes Unix (celles de l’âge de la pré-interface graphique) capitalisaient leurs noms de dossiers et rendaient les noms de fichiers non-capitalisés pour obtenir ce résultat automatiquement.
JRobert

Question utile! Peut-être qu'il est temps de changer la réponse acceptée en une réponse plus simple et ne brisant pas les couleurs du terminal?
ippi

Essayezls -lh --group-directories-first
Diogo

Réponses:


28

La commande suivante listera les répertoires en premier, les fichiers ordinaires en second et les liens en troisième.

ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep "^l"

En outre, il serait très judicieux de créer un alias pour cette commande afin de sauvegarder les frappes au clavier.

Modifier:

Si vous voulez d'abord les répertoires, puis tout ce qui n'est pas un répertoire, utilisez ceci:

ls -la | grep "^d" && ls -la | grep -v "^d"


1
Cette commande ne liste pas tout s'il y a, par exemple, des sockets ou des FIFO dans le dossier
Studer

1
Cette version modifiée devrait toujours fonctionner avec d'autres types. Le premier grep dit tout ce qui commence par un «d», et le second dit tout ce qui ne commence pas par un «d». Sûrement, tout commence par une annonce ou ne le fait pas, non?
Ry4an Brase

1
@ Mark - Pourquoi ne pas simplement faire: ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep -v -E "^d|^-|^total"?
FCTW

1
Pour que la commande de @ FCTW devienne un alias OSX, ajoutez ceci à votre ~ / .profile:alias la="ls -la | grep \"^d\" && ls -la | grep \"^-\" && ls -la | grep -E \"^d|^-\" -v | grep -v \"^total\""
aliteralmind

2
J'ai trouvé une notation plus courte: ls -la|grep ^d;ls -la|grep -v ^d(les guillemets ne sont pas obligatoires et sont remplacés &&par ;). Une autre option consiste à introduire une variable puis l' évaluer: a="ls -la|grep ^d";eval $a;eval $a -v. Pourrait être utile pour éviter les répétitions lorsque beaucoup plus d'options sont spécifiées pour ls/ grep. Il y a aussi cette ls -la --group-directories-firstoption, mais le plus court imo estls -la|sort
Steven Pribilinskiy

205

J'aime tellement * nix et j'adore voir l'inventivité qui entre dans certaines de ces réponses ...

Le mien n’est pas aussi sophistiqué sous GNU Linux:

alias ls='ls --color -h --group-directories-first'

Étant donné que je suis plus à l'aise avec mes applications linux CLI, j'ai également tendance à mettre à jour coreutils sur OSX:

brew install coreutils
alias ls='/usr/local/bin/gls --color -h --group-directories-first'

6
Malheureusement, cela ne fonctionne pas sur le terminal osx, car l'option n'est pas disponible.
MEM

7
re love: Est-ce que ce sarcasme? Si oui, je serais d'accord.
allyourcode

4
Le but de l'alias ls est de définir les éléments de configuration que je souhaite utiliser 90% du temps. Moins de frappes au clavier pour obtenir le résultat souhaité. Si vous voulez avoir une sortie native ls, vous pouvez toujours / bin / ls.
jonathanserafini

4
@MEM Si vous utilisez OS X et que vous aimez utiliser Terminal, vous devriez brew install bash alors, cela fonctionnera! :)
Andrew Ashbacher

5
Mon avis: cela aurait dû être la réponse acceptée, car elle répertorie une option en ligne de commande permettant d'atteindre exactement l'objectif, au lieu d'un ensemble compliqué de grep, etc.
Ryan Griggs

17

Pour les utilisateurs de Mac coreutils :

brew install coreutils

alias ls='ls --color -h --group-directories-first'

En supposant que votre système soit prêt à l' homebrew :


7
glsplutôt. Droite?
Paul irlandais le

1
Oui, par défaut Vous pouvez également utiliser coreutils par défaut avec PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH".
Benesch

7

Il y a certaines choses que je veux voir dans une liste de répertoires, et jusqu'à présent, aucune des réponses ici ne répond à toutes les exigences ci-dessous. Mes exigences pour une liste de répertoires:

  1. Les répertoires et les fichiers sont triés par ordre alphabétique
  2. Les répertoires sont listés en premier
  3. Les liens symboliques (liens symboliques) sont triés comme des fichiers
  4. Le tri est insensible à la casse
  5. Le tri ignore tous les principaux caractères non-alpha d'un nom de fichier
  6. La liste comprend le nombre total de répertoires (à l'exclusion de ./et ../), de fichiers et de liens.
  7. La liste comprend la taille totale (utilisation du disque) des répertoires et des fichiers
  8. La liste doit avoir le même aspect sous Linux et Windows (shell Git Bash) - c’était le plus difficile à comprendre, car des options pratiques telles --group-directories-firstque ne fonctionnent pas dans Git Bash pour Windows

Après de longues discussions, j'ai finalement trouvé un one-liner (bien que très long ;-)) dont je suis satisfait. J'ai assigné ceci à un alias nommé 'dir':

ls -dlF --color * .* | head -n2 && ls -AlF | LC_ALL=C grep "^d" | 
LC_ALL=C sort -k 9df && ls -AlF | LC_ALL=C grep "^[l-]" | 
LC_ALL=C sort -k 9df && echo -e `find -maxdepth 1 -type d ! -name . | 
wc -l` Dir\(s\) `du -hs | cut -f 1`\\t\\t`find -maxdepth 1 -type f | 
wc -l` File\(s\) `find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | 
tail -n 1 | cut -f 1`\\t\\t`find -maxdepth 1 -type l | wc -l` Link\(s\)

Pour rendre les choses plus faciles à gérer, j'ai créé des commandes distinctes pour extraire chaque segment de la liste de répertoires à mon goût, puis je les ai assemblées à l'aide de l' &&opérateur.

  • ls -dlF --color * .* | head -n2- Extrait ./et ../. Nous ne voulons pas les passer, sortcar ils sont déjà dans le bon ordre, et leur tri peut avoir pour conséquence de ../commencer par être répertoriés. L' -doption consiste à supprimer la ligne "totale"; J'aime ajouter -Fpour afficher la barre oblique de fin pour les répertoires (il marquera également les liens symboliques avec "@" lorsque vous faites un simple ls -F).

  • ls -AlF | LC_ALL=C grep "^d" | LC_ALL=C sort -k 9df- Extrayez les répertoires et triez-les par nom de fichier (9ème colonne), en ignorant les caractères non-alpha / space ( doption) et la casse des caractères ( foption). L' ls -Aoption exclut ./et ../de la liste puisque nous les avons déjà extraites à l'étape précédente. J'ai tendance à préfixer tout grepet les sortcommandes avec les LC_ALL=Cparamètres régionaux réinitialisés pour que (1) la sortie soit cohérente sur les shells Unix, et (2) vous obtiendrez parfois des performances plus rapides car le surcoût du lourd jeu de caractères UTF-8 ne traiter avec.

  • ls -AlF | LC_ALL=C grep "^[l-]" | LC_ALL=C sort -k 9df - Ceci est similaire à l'étape ci-dessus, mais cette fois, nous trions des fichiers et des liens symboliques.

  • find -maxdepth 1 -type d ! -name . | wc -l- Obtenir le nombre de répertoires, à l'exclusion de ./et ../.

  • find -maxdepth 1 -type f | wc -l - Récupère le nombre de fichiers.

  • find -maxdepth 1 -type l | wc -l - Obtenez le nombre de liens symboliques.

  • du -hs | cut -f 1 - Extraire la taille totale de tous les sous-répertoires dans un format lisible par l'homme.

  • find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | tail -n 1 | cut -f 1 - Extrayez la taille totale de tous les fichiers dans un format lisible par l'homme.

Voyons notre nouvel diralias en action!

AVANT:

$ ls -alF
total 22
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/

APRÈS:

$ dir
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
      5 Dir(s) 2.8M           6 File(s) 31K           0 Link(s)

Un inconvénient mineur est que vous ne pouvez pas avoir de listes colorées, car les caractères de contrôle de la couleur entourant les noms de fichiers rendent le tri trop peu fiable.


MISE À JOUR

L'alias ci-dessus était extrêmement lent à l'exécution du répertoire racine d'un système de fichiers profond. J'ai donc mis à jour cette commande plus simple mais beaucoup plus performante:

ls -AFoqv --color --group-directories-first | tail -n +2 && find -maxdepth 1 -type f -printf '%s\n' | awk '{total+=$1} END {print total" bytes"}'

Exemple de sortie:

$ dir
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .aws/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .gem/
drwxr-xr-x 1 Tom     0 Mar 29 19:32 .ssh/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .zbstudio/
drwxr-xr-x 1 Tom     0 Jun 16  2016 temp/
drwxr-xr-x 1 Tom     0 Jul 13  2016 vimfiles/
-rw-r--r-- 2 Tom   365 Mar 30 10:37 .aliases
-rw-r--r-- 1 Tom 16028 Mar 30 12:12 .bash_history
-rw-r--r-- 2 Tom  2807 Mar 30 12:12 .bash_profile
-rw-r--r-- 2 Tom  2177 Mar 29 23:24 .functions
-rw-r--r-- 1 Tom  1091 Mar 30 10:34 .gitconfig
-rw-r--r-- 1 Tom  8907 Mar 29 14:45 _viminfo
-rw-r--r-- 1 Tom  2444 Jul 13  2016 _vimrc
33819 bytes

Depuis la prise en charge de la nouvelle version de Git Bash pour Windows --group-directories-first, nous n’avons plus à nous en remettre sort. Même si le nouvel alias n'affiche pas autant d'informations que l'ancien, les gains de performances en valent la peine. En tant qu'avantage, vous obtenez également des couleurs!


Très bonne réponse! Mais quand vous dites: «Après de nombreuses discussions, j'ai finalement trouvé un one-liner ...» . En effet, ce n'est pas vraiment un «one-liner» au sens classique du terme. Il serait peut-être judicieux de prendre cette logique pour en faire un script shell autonome et de simplement l'exécuter ou de l'appeler comme un alias.
JakeGould

@JakeGould Vous êtes rapide! Je n'ai même pas encore fini de relire ma réponse et vous avez déjà fini de la lire et vous avez tiré un commentaire :). Oui, c'est un candidat de choix pour une fonction, mais j'étais trop paresseux à l'époque, alors jetez-le dans mon fichier .bash_aliases. D'un autre côté, je n'écris habituellement une fonction que lorsque je ne peux pas faire quelque chose sans passer de paramètres.
jeudi

@ 10basetom: Question rapide: Comment obtenir les différentes couleurs pour les colonnes dans ls? Je peux colorer les noms de fichiers par type de fichier à l'aide de ls --color, mais je ne vois pas comment obtenir ces couleurs utiles pour les colonnes. Quel est le secret?
Pirx

@Pirx Je pense que les colonnes sont colorées par la coloration syntaxique par défaut de Stack Exchange :-).
thdoan

Oui, cela semble être le cas, mais c'est une bonne idée et des solutions existent ;-)
Pirx

6

Vous avez plusieurs choix, selon que vous souhaitez conserver l'ordre alphabétique.

Vous pouvez simplement essayer:

ls -al | trier -k1 -r

ou cela, pour conserver l'ordre alphabétique des fichiers avec les mêmes autorisations:

ls -al | trier -k1,1 -k9,9 -r

ou, comme le dit onze81 (mais cette version énumère tout):

ls -la | grep "^ d" && ls -la | grep "^ -" && ls -al | grep -v "^ [d | -]"


1
C’est une solution plus intéressante, OMI. Utiliser plusieurs processus et conduites pour effectuer le tri au lieu de la tuyauterie semble trier à l'envers. Surtout depuis ls- al|sort -k1 -rfonctionne. Ce qui manquait, c'est juste le -rdrapeau.
Brice

@brice La chose qui me dérange au sujet de "sorte" est que ./et ../ne sera pas les deux premières lignes, dans cet ordre. En dehors de cela, je conviens que c'est la solution la plus efficace.
jeudi

Comment colorer la sortie?
Danijel le

5

À la réponse de delerious010 , j'ajouterais que si vous souhaitez commander à l'ancienne:

LANG=C ls -la --group-directories-first

(ou utilisez LC_ALL ou LANGUAGE ou LC_COLLATE réglé sur "C").

Cela donnera quelque chose de similaire à:

.
..
DIR
Dir
dir
.hidden
123
UC_FILE
Uc_file
lc_file

Bien que, si je me souvienne bien, les fichiers à points cachés sont apparus avant les répertoires.


2

Voici une fonction pour faire ceci (bash ou zsh): Et ... je ne suggère pas que ce soit la meilleure façon, mais c'est celle que j'ai créée et que j'utilise en ce moment:

fonction lss
{
    # Affiche la liste des répertoires avec les répertoires en haut.

    commande ls --color = always $ @ | egrep '^ d | total'
    commande ls --color = always $ @ | egrep -v '^ d | total';
}

Juste un fyi cela ne semble pas fonctionner. Vous devez utiliser le format de liste longue ( ls -l) afin de filtrer par type de fichier comme celui-ci. En outre, cette commande sera brisée sur les espaces (en bash). Vous devez citer comme suit: "$@"Si vous souhaitez utiliser cette approche, vous pouvez faire quelque chose comme ceci:function lss {local temp="$(command ls -l --color=always "$@")"; egrep --color=never '^d|total' <<<"$temp"; egrep --color=never -v '^d|total' <<<"$temp"}
Six

2

ls -laX vous montrera d’abord les répertoires dans l’ordre alphabétique, mais videra la liste des fichiers.

Longues options:

ls
    -l    # List
    --all
    -X    # Sort alphabetically by entry extension

Cela ne fonctionnerait que si vous pouviez être absolument certain que chaque répertoire n'avait pas de point dans son nom.
eleven81

1

Autrement ...

find . -d 1 -type d | ls -la | sort -r 

OU

ls -la | sort -r

OU

d=`find . -type d -d 1`;f=`find . -type f -d 1`; echo -e -DIRS- "\n$d\n" -FILES- "\n$f"

Que font-ils? Où avez-vous appris à les taper?
Tamara Wijsman

Bien, mon système d’exploitation préféré est Debian Linux. La version du paquet gnu core utils de Debian de ls prend en charge l'option --show-Directories-first ... quand j'ai commencé à utiliser OSX, j'ai simplement saisi tous mes fichiers de points bash de ma boîte Debian et les ai déposés dans mon répertoire personnel ... I eu beaucoup de bash_aliases qui ont éclaté alors ... C'est alors que je devais trouver une solution de contournement pour mes alias ...
Eddie B

Le premier est un peu redondant ... Il n'y a vraiment aucune raison de trier les répertoires car c'est l'ordre que nous devons modifier, pas les répertoires ... le 'ls -la | sorte -r 'est ce qui fonctionne vraiment. Fondamentalement, c'est énoncé ... 1) A) Trouver. -d 1 -type d (Commencez à partir de ce répertoire, recherchez une profondeur de répertoire et recherchez uniquement les répertoires) B) ls -la (liste les fichiers avec tous les attributs) C) Triez-les à l'envers 2) Faites comme 1) déposez simplement la recherche. .. ce n'est pas nécessaire ... j'aime mieux la solution de Studers ... :-)
Eddie B

1

TL; DR

alias ls='ls -lhF --color'

list_sorted() {
    ls $* | grep "^d";
    ls $* | grep "^-";
    ls $* | grep -v -E "^d|^-|^total"
}

alias ll=list_sorted

Explication

J'utilise une combinaison des solutions fournies dans les réponses et les commentaires ici.

Défaut ls

Tout d’abord, je remplace le comportement par défaut pour ls:

  • -l: Affiche toujours la liste sous forme de liste unidimensionnelle verticale
  • -h: Affiche la taille des fichiers de manière lisible par l’homme (par exemple, 4.0K au lieu de 4096)
  • -F: Afficher les indicateurs comme une barre oblique de fin pour les répertoires
alias ls='ls -lhF --color'

Élargi ll

Ensuite, j'écris une fonction contenant la logique de tri. Pour chacun, lsje lui passe les arguments initialement transmis. Cela me permet d'utiliser l'alias à partir d'un répertoire de travail différent de celui que je veux lister (c'est-à-dire ls -a ~).

En outre, chaque appel à lsest dirigé vers une grepcommande. Ici, le tri se passe. ls -l | grep "^d"par exemple, ne répertorie que les répertoires. Si les répertoires doivent être répertoriés en premier, cela doit également figurer en premier dans la fonction. La prochaine chose est les fichiers.

Enfin, je montre tout ce qui n'est ni un répertoire ni un fichier (ni la ligne indiquant la taille totale du contenu du répertoire). Cela se fait par grepping directoy, les entrées de fichier normales et l'entrée totale, puis en inversant le résultat via l' -vargument.

list_sorted() {
    # List directories
    ls $* | grep "^d";
    # List regular files
    ls $* | grep "^-";
    # List everything else (e.g. symbolic links)
    ls $* | grep -v -E "^d|^-|^total"
}

Enfin, j'appelle la fonction à une nouvelle commande. En particulier, je ne veux pas écraser lsau cas où ma fonction serait brisée dans certains scénarios. Ensuite, je veux pouvoir utiliser ls. Sinon, vous pouvez toujours invoquer la lscommande sans alias en l'invoquant \ls.

alias ll=list_sorted

Remarques

  • J'utilise ;au lieu de &&comme un délimiteur pour les commandes. Sinon, il est impossible de répertorier le contenu des répertoires ne contenant pas de répertoires (la première commande ls est évaluée à false, ce qui ne permet pas l'exécution de la commande suivante car elle est associée à &&. ;Evite that.)

0

Ceci est une solution de script. Répertorie uniquement les noms, pas de données inode, alphabétiques, non sensibles à la casse, formatés en colonnes. Bien que ce soit ligne-majeur au lieu de colonne majeure comme la sortie par défaut de ls. Les colonnes sont un peu en désordre s'il existe un nom de fichier de> 26 caractères.

rm -f /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout

IFS=$'\n' read -d '' -r -a lines < /tmp/lsout

printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

Et un autre, avec un formatage supplémentaire.

rm -f /tmp/lsout
echo "  ---- Directories ---- " >> /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

rm -f /tmp/lsout
echo "  ------- Files ------- " >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

La sortie pour le dernier ressemble à ceci, moins les couleurs:

  ---- Directories ----   archive/                  bookmarks/              
Desktop/                  Documents/                Downloads/              
fff/                      health/                   Library/                
Movies/                   Music/                    Pictures/               
Public/                   rrf/                      scifi/            
testdir/                  testdir2/                                         
  ------- Files -------   @todo                     comedy            
delme                     lll                       maxims                  
schedule                  vtokens style

Rappelez-vous simplement de ne pas alias ou de changer le comportement par défaut de ls puisque ce script l’appelle.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.