Lister uniquement les répertoires utilisant ls dans bash: Un examen

Cette commande répertorie les répertoires du chemin actuel: ls -d */

Que fait exactement le pattern */ do?

Et comment pouvons-nous donner le chemin absolu dans la commande ci-dessus (par exemple, ls -d /home/alice/Documents ) pour ne lister que les répertoires de ce chemin?

*/ est un modèle qui correspond à tous les sous-répertoires du répertoire en cours ( * correspond à tous les fichiers et sous répertoires; le / restreint aux répertoires). De même, pour lister tous les sous-répertoires sous / home / alice / Documents, utilisez ls -d /home/alice/Documents/*/

Quatre façons de faire cela, chacune avec un format de sortie différent

1. Utiliser l’ echo

Exemple: echo */ , echo */*/
Voici ce que j’ai eu:

 cs/ draft/ files/ hacks/ masters/ static/ cs/code/ files/images/ static/images/ static/stylesheets/ 

2. Utiliser uniquement ls

Exemple: ls -d */
Voici exactement ce que j’ai eu:

 cs/ files/ masters/ draft/ hacks/ static/ 

Ou comme liste (avec informations détaillées): ls -dl */

3. Utiliser ls et grep

Exemple: ls -l | grep "^d" ls -l | grep "^d" Voici ce que j’ai eu:

 drwxr-xr-x 24 h staff 816 Jun 8 10:55 cs drwxr-xr-x 6 h staff 204 Jun 8 10:55 draft drwxr-xr-x 9 h staff 306 Jun 8 10:55 files drwxr-xr-x 2 h staff 68 Jun 9 13:19 hacks drwxr-xr-x 6 h staff 204 Jun 8 10:55 masters drwxr-xr-x 4 h staff 136 Jun 8 10:55 static 

4. Bash Script (non recommandé pour les noms de fichiers contenant des espaces)

Exemple: for i in $(ls -d */); do echo ${i%%/}; done for i in $(ls -d */); do echo ${i%%/}; done
Voici ce que j’ai eu:

 cs draft files hacks masters static 

Si vous souhaitez avoir ‘/’ comme caractère de fin, la commande sera: for i in $(ls -d */); do echo ${i}; done for i in $(ls -d */); do echo ${i}; done

 cs/ draft/ files/ hacks/ masters/ static/ 

J’utilise:

 ls -d */ | cut -f1 -d'/' 

Cela crée une seule colonne sans barre oblique – utile dans les scripts.

Mes deux centimes.

Pour tous les dossiers sans sous-dossiers:

 find /home/alice/Documents -maxdepth 1 -type d 

Pour tous les dossiers avec sous-dossiers:

 find /home/alice/Documents -type d 

4 (plus) Options fiables.

Un astérisque non cité * sera interprété comme un motif (glob) par le shell.
Le shell l’utilisera pour l’expansion des chemins d’access.
Il générera ensuite une liste de noms de fichiers correspondant au modèle.
Un simple astérisque correspondra à tous les noms de fichiers dans le PWD (répertoire de travail actuel).
Un modèle plus complexe comme */ correspondra à tous les noms de fichiers qui se terminent par / .
Ainsi, tous les répertoires. C’est pourquoi la commande:

1.- écho.

 echo */ echo ./*/ ### avoid misinterpreting filenames like "-e dir" 

sera développé (par le shell) pour echo tous les répertoires du PWD.


Pour tester ceci: Créez un répertoire ( mkdir ) nommé comme test-dir et cd dedans:

 mkdir test-dir; cd test-dir 

Créez des répertoires:

 mkdir {cs,files,masters,draft,static} # safe directories. mkdir {*,-,--,-v\ var,-h,-n,dir\ with\ spaces} # some a bit less secure. touch -- 'file with spaces' '-a' '-l' 'filename' # and some files: 

La commande echo ./*/ restra fiable même avec des fichiers nommés impairs:

 ./--/ ./-/ ./*/ ./cs/ ./dir with spaces/ ./draft/ ./files/ ./-h/ ./masters/ ./-n/ ./static/ ./-v var/ 

Mais les espaces dans les noms de fichiers rendent la lecture un peu confuse.


Si au lieu de l’ echo , on utilise ls , le shell est toujours ce qui élargit la liste des noms de fichiers. Le shell est la raison pour obtenir une liste de répertoires dans le PWD. L’option -d à ls permet de lister l’entrée du répertoire actuel au lieu du contenu de chaque répertoire (comme présenté par défaut).

 ls -d */ 

Cependant, cette commande est (un peu) moins fiable. Il échouera avec les fichiers nommés impairs listés ci-dessus. Il s’étouffera avec plusieurs noms. Vous devez effacer un à un jusqu’à ce que vous trouviez ceux qui ont des problèmes.

2.- ls

Le GNU ls acceptera la touche “fin des options” ( -- ).

 ls -d ./*/ ### more reliable BSD ls ls -d -- */ ### more reliable GNU ls 

3.-printf

Pour répertorier chaque répertoire dans sa propre ligne (dans une colonne, similaire à ls -1), utilisez:

 $ printf "%s\n" */ ### Correct even with "-", spaces or newlines. 

Et, mieux encore, nous pourrions supprimer le trailing / :

 $ set -- */; printf "%s\n" "${@%/}" ### Correct with spaces and newlines. 

Une tentative comme celle-ci:

 $ for i in $(ls -d */); do echo ${i%%/}; done 

Va échouer sur:

  • quelques noms ( ls -d */ ) comme déjà montré ci-dessus.
  • sera affecté par la valeur de l’ IFS .
  • divisera les noms sur les espaces et les tabs (avec IFS par défaut).
  • chaque nouvelle ligne du nom lancera une nouvelle commande echo.

4.- Fonction

Enfin, l’utilisation de la liste d’arguments dans une fonction n’affecte pas la liste des arguments du shell en cours d’exécution. Simplement:

 $ listdirs(){ set -- */; printf "%s\n" "${@%/}"; } $ listdirs 

présente cette liste:

 -- - * cs dir with spaces draft files -h masters -n static -v var 

Ces options sont sécurisées avec plusieurs types de noms de fichiers impairs.

La commande tree est également très utile ici. Par défaut, tous les fichiers et répertoires seront affichés avec une profondeur complète, certains caractères ascii affichant l’arborescence.

 $ tree . ├── config.dat ├── data │ ├── data1.bin │ ├── data2.inf │ └── sql | │ └── data3.sql ├── images │ ├── background.jpg │ ├── icon.gif │ └── logo.jpg ├── program.exe └── readme.txt 

Mais si nous voulions obtenir uniquement les répertoires, sans l’arborescence ASCII, et avec le chemin complet du répertoire actuel, vous pourriez faire:

 $ tree -dfi . ./data ./data/sql ./images 

Les arguments étant:

 -d List directories only. -f Prints the full path prefix for each file. -i Makes tree not print the indentation lines, useful when used in conjunction with the -f option. 

Et si vous voulez ensuite le chemin absolu, vous pouvez commencer par spécifier le chemin complet du répertoire en cours:

 $ tree -dfi "$(pwd)" /home/alice/Documents /home/alice/Documents/data /home/alice/Documents/data/sql /home/alice/Documents/images 

Et pour limiter le nombre de sous-répertoires, vous pouvez définir le niveau maximal des sous-répertoires avec le -L level , par exemple:

 $ tree -dfi -L 1 "$(pwd)" /home/alice/Documents /home/alice/Documents/data /home/alice/Documents/images 

Plus d’arguments peuvent être vus avec Man Tree

Dans le cas où vous vous demandez pourquoi la sortie de ‘ls -d * /’ vous donne deux barres obliques, comme:

 [prompt]$ ls -d */ app// cgi-bin// lib// pub// 

c’est probablement parce que quelque part vos fichiers de configuration de shell ou de session utilisent la commande ls pour une version de ls qui inclut l’indicateur -F. Cet indicateur ajoute un caractère à chaque nom de sortie (ce n’est pas un fichier simple) indiquant le type de chose qu’il est. Ainsi, une barre oblique correspond à celle du motif ‘* /’ et l’autre est la barre oblique.

Pour vous débarrasser de ce problème, vous pouvez bien entendu définir un alias différent pour ls. Toutefois, pour ne pas appeler temporairement l’alias, vous pouvez append la barre oblique inverse à la commande suivante:

\ ls -d * /

Je viens d’append ceci à mon fichier .bashrc (vous pouvez aussi le taper simplement sur la ligne de commande si vous n’en avez besoin que pour une session)

 alias lsd='ls -ld */' 

alors lsd produira le résultat désiré.

Si le répertoire caché n’a pas besoin d’être répertorié, je propose:

 ls -l | grep "^d" | awk -F" " '{print $9}' 

Et si des répertoires cachés doivent être répertoriés, utilisez:

 ls -Al | grep "^d" | awk -F" " '{print $9}' 

OU

 find -maxdepth 1 -type d | awk -F"./" '{print $2}' 

afficher les listes de dossiers sans /

 ls -d */|sed 's|[/]||g' 

Voici ce que j’utilise

ls -d1 /Directory/Path/*;

Solution ls réelle, y compris les liens symboliques vers les répertoires

Beaucoup de réponses ici n’utilisent pas vraiment ls (ou ne l’utilisent que dans le sens sortingvial de ls -d , tout en utilisant des caractères génériques pour la correspondance de sous-répertoires. Une solution true ls est utile, car elle permet d’utiliser les options ls , etc.

Hors symlinks

Une solution utilisant ls a été donnée, mais elle fait quelque chose de différent des autres solutions car elle exclut les liens symboliques vers les répertoires:

 ls -l | grep '^d' 

(éventuellement en passant par sed ou awk pour isoler les noms de fichiers)

Y compris les liens symboliques

Dans le cas (probablement plus courant) où des liens symboliques vers des répertoires devraient être inclus, nous pouvons utiliser l’option -p de ls :

 ls -1p | grep '/$' 

ou, se débarrasser des barres obliques:

 ls -1p | grep '/$' | sed 's/\/$//' 

Nous pouvons append des options à ls selon les besoins (si une longue liste est utilisée, la valeur -1 n’est plus requirejse).

note: si nous voulons des barres obliques, mais que nous ne voulons pas qu’elles soient mises en évidence par grep , nous pouvons supprimer cette mise en évidence en rendant vide la partie correspondante de la ligne:

 ls -1p | grep -P '(?=/$)' 

Testez si l’élément est un répertoire avec test -d :

 for i in $(ls); do test -d $i && echo $i ; done 

One-liner pour lister les répertoires uniquement à partir de “ici”.

Avec nombre de fichiers.

 for i in `ls -d */`; do g=`find ./$i -type f -print| wc -l`; echo "Directory $i contains $g files."; done 

*/ est un modèle de correspondance de nom de fichier qui correspond aux répertoires du répertoire en cours.

Pour lister uniquement les répertoires, j’aime cette fonction:

 # long list only directories llod () { ls -l --color=always "$@" | grep --color=never '^d' } 

Mettez-le dans votre .bashrc.

Exemples d’utilisation:

 llod # long listing of all directories in current directory llod -tr # same but in chronological order oldest first llod -da* # limit to directories beginning with letter 'a' llod -d .* # limit to hidden directories 

NOTE: il sera cassé si vous utilisez l’option -i . Voici un correctif pour cela:

 # long list only directories llod () { ls -l --color=always "$@" | egrep --color=never '^d|^[[:digit:]]+ d' } 

FYI, si vous voulez imprimer tous les fichiers sur plusieurs lignes, vous pouvez faire un ls -1 qui imprimera chaque fichier dans une ligne distincte. fichier1 fichier2 fichier3

En utilisant Perl:

 ls | perl -nle 'print if -d;' 

J’ai partiellement résolu avec:

 cd "/path/to/pricipal/folder" for i in $(ls -d .*/); do sudo ln -s "$PWD"/${i%%/} /home/inukaze/${i%%/}; done ln: «/home/inukaze/./.»: can't overwrite a directory ln: «/home/inukaze/../..»: can't overwrite a directory ln: accesing to «/home/inukaze/.config»: too much symbolics links levels ln: accesing to «/home/inukaze/.disruptive»: too much symbolics links levels ln: accesing to «/home/inukaze/innovations»: too much symbolics links levels ln: accesing to «/home/inukaze/sarl»: too much symbolics links levels ln: accesing to «/home/inukaze/.e_old»: too much symbolics links levels ln: accesing to «/home/inukaze/.gnome2_private»: too much symbolics links levels ln: accesing to «/home/inukaze/.gvfs»: too much symbolics links levels ln: accesing to «/home/inukaze/.kde»: too much symbolics links levels ln: accesing to «/home/inukaze/.local»: too much symbolics links levels ln: accesing to «/home/inukaze/.xVideoServiceThief»: too much symbolics links levels 

Eh bien, cela me réduit, la partie maire 🙂

Ajouter pour compléter le cercle, récupérer le chemin de chaque dossier, utiliser une combinaison de la réponse d’Albert et de Gordans qui devrait être très utile.

 for i in $(ls -d /pathto/parent/folder/*/); do echo ${i%%/}; done 

Sortie:

 /pathto/parent/folder/childfolder1/ /pathto/parent/folder/childfolder2/ /pathto/parent/folder/childfolder3/ /pathto/parent/folder/childfolder4/ /pathto/parent/folder/childfolder5/ /pathto/parent/folder/childfolder6/ /pathto/parent/folder/childfolder7/ /pathto/parent/folder/childfolder8/ 

Essaye celui-là. cela fonctionnera sur toutes les dissortingbutions ls -ltr | grep drw

Pour répertorier uniquement les répertoires :

 ls -l | grep ^d 

pour lister uniquement les fichiers :

 ls -l | grep -v ^d 

ou aussi vous pouvez faire comme: ls -ld * /

 file *|grep directory 

O / P (Sur ma machine) –

 [root@rhel6 ~]# file *|grep directory mongo-example-master: directory nostarch: directory scriptzz: directory splunk: directory testdir: directory 

La production ci-dessus peut être affinée davantage en utilisant la coupe.

 file *|grep directory|cut -d':' -f1 mongo-example-master nostarch scriptzz splunk testdir * could be replaced with any path that's permitted file - determine file type grep - searches for ssortingng named directory -d - to specify a field delimiter -f1 - denotes field 1