web-dev-qa-db-fra.com

Liste uniquement des répertoires utilisant ls dans bash: un examen

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

Que fait exactement le motif */?

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

791
Sibi

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

843
Gordon Davisson

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

1. Utilisation de 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. Utilisation de ls uniquement

Exemple: ls -d */
Voici exactement ce que j'ai obtenu: 

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

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

3. Utiliser ls et grep

Exemple: ls -l | grep "^d"Voici ce que j'ai obtenu:

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. Script Bash (non recommandé pour le nom de fichier contenant des espaces)

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

cs  
draft  
files  
hacks  
masters  
static

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

cs/  
draft/  
files/  
hacks/  
masters/  
static/
423
Albert

J'utilise:

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

Cela crée une colonne unique sans barre oblique - utile dans les scripts.

Mes deux centimes.

80
Thomas Altfather Good

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
46
at3m

4 (plus) options fiables.

Un uncoted asterisk * sera interprété comme un motif (glob) par le shell.
Le shell l'utilisera dans l'extension du chemin d'accès.
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 de la PWD (répertoire de travail actuel).
Un modèle plus complexe comme */ correspondra à tous les noms de fichiers se terminant par /.
Ainsi, tous les annuaires. C'est pourquoi la commande:

1.- écho.

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

sera étendu (par le shell) à echo tous les répertoires de la PWD.


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

mkdir test-dir; cd test-dir

Créer 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 ./*/ restera 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 déroutante.


Si, au lieu de echo, nous utilisons ls, le shell continue d’élargir la liste des noms de fichiers. Le shell est la raison pour obtenir une liste de répertoires dans la PWD. L'option -d dans ls lui permet de répertorier l'entrée du répertoire présent au lieu du contenu de chaque répertoire (tel que présenté par défaut).

ls -d */

Cependant, cette commande est (un peu) moins fiable. Il échouera avec les fichiers nommés impairs énumérés ci-dessus. Il va s'étouffer avec plusieurs noms. Vous devez effacer un par un jusqu'à trouver ceux qui ont des problèmes.

2.- ls

La GNU ls acceptera la touche "fin d’options" (--).

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

3.-printf

Pour lister 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 / suivant:

$ 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:

  • certains noms (ls -d */) comme déjà montré ci-dessus.
  • sera affecté par la valeur de IFS.
  • divisera les noms en espaces et en onglets (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'affectera pas la liste d'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.

32
user2350426

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, avec quelques caractères ascii indiquant l’arborescence des répertoires.

$ 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 actuel:

$ 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 de sous-répertoires avec -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

16
Hamish Downer

Dans le cas où vous vous demanderiez pourquoi la sortie de 'ls -d * /' vous donne deux barres de fin, 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 appellent la commande ls une version de ls incluant l'indicateur -F Cet indicateur ajoute un caractère à chaque nom de sortie (ce n'est pas un fichier brut) indiquant le type de document. Ainsi, une barre oblique correspond au type correspondant au motif '* /', et l’autre barre oblique est l’indicateur de type ajouté.

Pour résoudre ce problème, vous pouvez bien sûr définir un alias différent pour ls. Cependant, pour ne pas appeler temporairement l'alias, vous pouvez ajouter une barre oblique inversée à la commande:

\ ls -d * /

11
gwideman

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

alias lsd='ls -ld */'

alors lsd produira le résultat souhaité.

9

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 vous avez besoin de répertoires cachés, utilisez:

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

OR

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

afficher des listes de dossiers sans /

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

Pour lister seulement répertoires :

ls -l | grep ^d

pour lister seulement fichiers :

ls -l | grep -v ^d 

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

6
Vijay Gawas

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

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

Hors liens symboliques

Une solution utilisant ls a été donnée, mais elle fait quelque chose de différent des autres solutions en ce qu'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) d'inclusion de liens symboliques vers des répertoires, nous pouvons utiliser l'option -p de ls:

ls -1p | grep '/$'

ou, se débarrasser des barres obliques de fin:

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

Nous pouvons ajouter des options à ls si nécessaire (si une longue liste est utilisée, le -1 n'est plus requis).

remarque: si nous voulons ajouter des barres obliques, mais nous ne voulons pas qu'elles soient mises en évidence par grep, nous pouvons supprimer la mise en surbrillance en rendant vide la partie correspondante de la ligne:

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

Voici ce que j'utilise 

ls -d1 /Directory/Path/*;

5
Banning

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

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

*/ 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 -d a* # limit to directories beginning with letter 'a'
llod -d .* # limit to hidden directories

REMARQUE: cela cassera 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'
}
2
Robin A. Meade

Pour votre information, si vous voulez imprimer tous les fichiers sur plusieurs lignes, vous pouvez créer un ls -1 qui imprimera chaque fichier sur une ligne séparée. fichier1 fichier2 fichier3

2
warfreak92

One-Liner pour lister les répertoires uniquement à partir de "ici".

Avec le nombre de fichiers.

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

Utiliser Perl:

ls | Perl -nle 'print if -d;'
2

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

1
Raj RD

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, ceci me réduit la partie maire :)

1
inukaze

Pour répondre à la question initiale, */ n'a rien à voir avec ls en soi; cela est fait par Shell/Bash, dans un processus appelé globbing .

C'est pourquoi echo */ et ls -d */ affichent les mêmes éléments. (L'indicateur -d permet à ls de générer les noms de répertoire et non le contenu des répertoires.)

1
flow2k

Pour ajouter le cercle complet, pour récupérer le chemin de chaque dossier, utilisez une combinaison des réponses 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/
1
BilliAm

Une liste simple du répertoire actuel, ce serait:

ls -1d ./*/

Voulez-vous qu'il soit trié et propre?

ls -1d ./*/ | cut -c 3- | rev | cut -c 2- | rev | sort
0
PYK

Voici ce que j'utilise pour lister uniquement les noms de répertoires:

ls -1d /some/folder/*/ | awk -F "/" "{print \$(NF-1)}"
0
Robert Lujo
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 sortie ci-dessus peut être affinée davantage en utilisant cut.

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 string named directory
 -d - to specify a field delimiter
 -f1 - denotes field 1
0
AVS

Voici une variante utilisant un arbre qui affiche les noms de répertoires uniquement sur des lignes distinctes, oui, c'est moche, mais bon, ça marche.

tree -d | grep -E '^[├|└]' | cut -d ' ' -f2

ou avec awk

tree -d | grep -E '^[├|└]' | awk '{print $2}'

C’est probablement mieux et conservera le / après le nom du répertoire.

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