Liste des sous-répertoires uniquement n profond


58

Festival stocke les données de Voicepack dans l'exemple de structure de répertoires suivant:

/usr/share/festival/voices/<language>/<voicepack name>

Quel est le système le plus simple utilisé par une seule ligne (de préférence, à utiliser ls) pour n’imprimer que le <voicepack name>, dans tous les <language>sous-répertoires potentiellement nombreux ?

Réponses:


80

Je suis sur Fedora, et ces VoicePacks sont dans un endroit légèrement différent:

$ ls /usr/share/festival/lib/voices/*/ -1 | grep -vE "/usr|^$"
kal_diphone
ked_diphone
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_rms_arctic_hts
nitech_us_slt_arctic_hts

Vous pouvez simplement modifier ceci comme ceci:

$ ls /usr/share/festival/voices/*/ -1 | grep -vE "/usr|^$"

Utiliser find

L'utilisation lsdans ce manoir est généralement mal vue parce que la sortie de lsest difficile à analyser. Mieux vaut utiliser la findcommande, comme ceci:

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -exec basename {} \;
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_slt_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_rms_arctic_hts
ked_diphone
kal_diphone

Détails de find & basename

Cette commande produit une liste de chemins complets vers des fichiers ayant exactement deux niveaux de profondeur par rapport à ce répertoire:

/usr/share/festival/lib/voices

Cette liste ressemble à ceci:

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 
/usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_bdl_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_slt_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_jmk_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_clb_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_rms_arctic_hts
/usr/share/festival/lib/voices/english/ked_diphone
/usr/share/festival/lib/voices/english/kal_diphon

Mais nous voulons la dernière partie de ces répertoires, le nœud feuille. Nous pouvons donc utiliser basenamepour l’analyser:

$ basename /usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
nitech_us_awb_arctic_hts

En réunissant tout cela, nous pouvons faire en sorte que la findcommande transmette chaque répertoire de niveau 2 à la basenamecommande. La notation basename {}est ce qui fait ces conversions de nom de base. Trouver des appels via son -execcommutateur.


lol, à peu près exactement la même réponse, grands esprits et tout ça :).
terdon

+1 - Pour ceux qui se fâchent en découvrant ce qui se -exec basename {}passe, pourriez-vous expliquer ici?
user66001

@ user66001 - laissez-moi savoir si cela explique assez.
slm

@ user66001 - vous pouvez accepter l'une des réponses si cela résout votre problème à votre satisfaction 8-)
slm

1
La commande find est ce dont j'ai besoin 99% du temps. Limiter les max et min était la clé - je n'ai fait que max. Exemple: recherche find ~/ -maxdepth 1 -mindepth 1 -type d | xargs du -csh | sort -h les plus gros répertoires triés par taille
oligofren

23

Le plus simple est

ls -d /usr/share/festival/voices/*/*

Cela est étendu par le shell à tous les sous-répertoires de /usr/share/festival/voices/, puis au contenu de chacun de ces sous-répertoires.

Si vous souhaitez uniquement descendre à un niveau spécifique, comme le suggère votre titre, avec des implémentations findtelles que GNU et BSD:

find /usr/share/festival/voices/ -mindepth 2 -maxdepth 3 -type d

Cela trouvera tous les répertoires ( -type d) qui se trouvent dans un sous-répertoire à /usr/share/festival/voices/cause de mindepth 2mais pas plus profonds que 3 niveaux inférieurs ( maxdepth 3). De man find:

   -maxdepth levels
          Descend at most levels (a non-negative integer) levels of direc
          tories below the command line arguments.  -maxdepth 0
           means only apply the tests and  actions  to  the  command  line
          arguments.

   -mindepth levels
          Do  not apply any tests or actions at levels less than levels (a
          non-negative integer).  -mindepth  1  means  process  all  files
          except the command line arguments.

Ouais c'est comme regarder dans un miroir 8-)
slm

+1 La façon dont vous avez tous les deux obtenu 2 votes est intéressante. Les votes croisés expliquent 1 chacun;) PS Je voulais des noms de répertoires, donc changer -type fen -type ddevrait résoudre cela, non? Attendra également la réponse de slm concernant le but de-exec basename {}
user66001

@ user66001 oui, vous -type dtrouverez des répertoires. C'est basenameune très bonne idée, cela n'imprimera que le nom et supprimera le chemin. En supposant que vous ne vouliez que des noms, c'est ce que vous devriez faire. Regardez man basenameet aussi man dirname.
terdon

Merci terdon - Désolé de ne pas avoir marqué ta réponse. A estimé que la version actuelle de slm de plus d' informations, a pour ceux qui en ont besoin.
user66001

1
@ user66001 tout d'abord, vous avez absolument raison, slm's est en effet meilleur. Deuxièmement, vous ne devriez jamais vous excuser de ne pas accepter, il ne peut y en avoir qu’un seul et c’est celui qui vous convient le mieux :).
terdon

6

La réponse acceptée fonctionne correctement mais est quelque peu inefficace car elle génère un nouveau basenameprocessus pour chaque sous-répertoire:

find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -exec basename {} \;

Dans la mesure du possible, il est préférable d’utiliser les fonctionnalités intégrées findafin d’éviter les coûts liés aux processus de génération. findpossède une capacité assez étendue pour modifier sa sortie imprimée à l'aide de l' -printfaction. L' -print action par défaut imprime l'intégralité du chemin, mais en utilisant -printfune chaîne de format, il est possible de sélectionner des parties du chemin à imprimer. Pour extraire uniquement la partie du nom de fichier du chemin d'accès sans les répertoires de début (comme c'est le basename cas), la chaîne de formatage est %f. Pour placer une nouvelle ligne après chaque nom de fichier, incluez ce \nqui suit:

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -printf '%f\n'
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_slt_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_rms_arctic_hts
ked_diphone
kal_diphone

+1 Merci pour votre réponse, Michael. Je peux voir l'avantage de la façon de procéder dans votre réponse, également, mais étant donné le travail mis dans la réponse de slm, je suis tout à fait décidé à changer la réponse acceptée. Si @slm le voit et n'a pas de problème à le choisir, je reviendrai ici pour modifier la réponse acceptée.
user66001

1
La réponse de @ slm est bien expliquée et couvre le schéma plus général d'utilisation findavec des commandes externes arbitraires; c'est tout simplement moins efficace pour les opérations intégrées find. J'avais envisagé d'ajouter un commentaire à sa réponse, mais cela nécessite plus de réputation que moi. Il n'est pas nécessaire de changer votre réponse acceptée, car la réponse actuellement acceptée est correcte, bien expliquée et utilisable comme modèle pour le cas plus général. Je voulais seulement souligner que, dans ce cas particulier, il existe une méthode plus efficace.
Michael Henry

0

TLDR; pour ceux qui viennent juste ici sur la base du titre de cette question; sur "Répertorier uniquement les sous-répertoires de niveau n profond": utilisez

find -maxdepth N

Nest n'importe quel nombre.

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.