Obtenir une liste de noms de répertoires avec find

35

Je sais que je peux le faire pour obtenir une liste de noms de répertoires:

find . -type d -maxdepth 1 

La sortie ressemble à ceci:

.
./foo
./bar

Je préfère la liste sans ./. Existe-t-il un moyen d'obtenir find pour sortir uniquement les noms bruts?

J'ai essayé d'envoyer la liste à stat pour la formater mais cela me donne le même résultat:

find . -type d -maxdepth 1 -print0 | xargs -0 stat -f '%N'
Joachim
la source
alors vous voulez foo bar ...tout sur une seule ligne sans le ./devant?
Levon
Est-ce uniquement pour des raisons cosmétiques / esthétiques ou essayez-vous de faire quelque chose avec la sortie?
jw013

Réponses:

42

Avec GNU, findvous pouvez utiliser l’ -printfoption:

find . -maxdepth 1 -type d -printf '%f\n'

Comme l'a noté Paweł dans les commentaires, si vous ne voulez pas que le répertoire courant soit répertorié, ajoutez-le -mindepth 1, par exemple:

find . -mindepth 1 -maxdepth 1 -type d -printf '%f\n'
Thor
la source
Je ne trouve aucune mention de l' -printfoption dans la dernière spécification POSIX et je me demande à quel point elle est portable ...
rahmu
@rahmu: Cela a été testé avec la recherche GNU. Aucune des printfoptions proposées n’est mentionnée par POSIX et elles ne semblent pas être supportées par certaines des autres findversions. GNU find peut être installé dans la plupart des endroits, il est donc portable.
Thor
1
ajoutez également -mindepth 1si vous voulez vous débarrasser de la.
Paweł Prażak le
18

Mise à jour:

Une alternative plus courte:

 find . -maxdepth 1 -type d | cut -c 3-

Vous donnera les noms, un par ligne, sans barres obliques

Levon
la source
4
@ downvoter .. un vote négatif sans explication n'aide personne (OP, SO ou moi). C'est une solution fonctionnelle à la question de OP. Je suis heureux de corriger une erreur si elle est signalée ou d'améliorer la réponse, mais cela nécessite des commentaires constructifs plutôt qu'un simple "clic" anonyme.
Levon
1
Je suis celui qui a voté lorsque votre réponse incluait l'analyse syntaxique ls. En même temps, j'avais posté un lien expliquant pourquoi il s'agissait d'une mauvaise idée pour une autre réponse supprimée depuis. À l'époque, il n'y avait que 2 réponses et la raison semblait évidente. Je suis content que vous ayez souligné l'ambiguïté, et voici mon explication. Pour mémoire, j’ai tourné mon vote vers le bas en vote positif, car je suis d’accord avec votre réponse actuelle.
Rahmu
@rahmu Donner une explication de votre vote négatif dans une autre question ne m’aide en rien (et reste évident pour vous). De plus, bien que ce soit une meilleure solution, la solution que j'avais déjà publiée fonctionnait parfaitement (oui, je connais votre lien "ne pas utiliser ls", mais il ne s'applique pas à l'aveuglette dans tous les cas). Si vous avez un exemple contre lequel ma solution initiale n'aurait pas fonctionné, j'aimerais le savoir (afin que je puisse réellement en apprendre quelque chose), sinon vous publiez simplement un lien et ne proposez rien de constructif.
Levon
Considérez qu’il existe un \nnom de répertoire que vous ne pouvez pas utiliser, cut, pour le récupérer (ce que vous faisiez lorsque je vous ai voté contre). Il y a peu de cas où il lsne se comporte pas de manière dangereuse et il est presque toujours plus prudent d'utiliser une autre méthode.
Rahmu
9

Avec GNU find, vous pouvez utiliser -mindepth pour empêcher find de correspondre au répertoire actuel:

find . -type d -maxdepth 1 -mindepth 1

Comme vous ne le faites pas de manière récursive, vous pouvez utiliser un bash glob:

echo */

L'ajout d'une fin / à un glob ne fera correspondre que les répertoires.

Jordan
la source
1
*/manque les fichiers de points et inclut les liens symboliques. Cela peut ou peut ne pas être un problème.
Gilles, arrête de faire le mal
@Gilles - Il manquera toujours des liens symboliques, mais les fichiers de points dépendent du fait que dotglob est défini ou non.
Jordan
6

Laissez sedsupprimer ces deux personnages:

find . -maxdepth 1 -type d | sed -e 's/^\.\///'
Birei
la source
6

Je préfère utiliser:

 find ./ -type d -maxdepth 1 -exec basename {} \;
utilisateur1293137
la source
2

J'utilise habituellement:

find * -type d

Mais je ne sais pas si c'est la bonne façon de faire ce que vous voulez.

Francesco Turco
la source
1
Si vous laissez le shell développer tous les noms de fichiers, pourquoi utiliser find du tout?
Jordanie
@jordanm Pour sélectionner uniquement les répertoires. echo */ferait la même chose, plus ou moins (il manque des fichiers de points et inclut des liens symboliques), mais alors joachim demanderait comment supprimer la finale /.
Gilles, arrête de faire le mal
0

Sous AIX, le paramètre "maxdepth" ne fonctionne pas.

En général, cela fonctionne pour moi:

find ./ -type d | cut -d"/" -f2 | sort -u

utilisateur1656294
la source
0

Ce que vous recherchez s'appelle basename, il ignore la structure de répertoires unix

Exemple ci-dessous:

find /any/path/you/want -maxdepth 1 -type d -exec basename {} \;

il exclura pour la sortie même le chemin du répertoire, supprimant la nécessité d’ cd exécuter la commande avant


Quelques informations supplémentaires:

Je passerais -execen argument pour trouver à la place |(pipe) une autre commande pour la sortie (en évitant que la deuxième commande ne passe par chaque ligne de sortie, cela dit, cela dépendrait de la sortie pour améliorer les performances du script)

REMARQUE: les findoptions ne sont pas positionnelles (-maxdepth affecte les tests spécifiés avant lui ainsi que ceux spécifiés après).

Gonzalesraul
la source