Festival stocke les données du pack vocal dans l'exemple de structure de répertoire suivant:
/usr/share/festival/voices/<language>/<voicepack name>
Quelle est la simple ligne (en utilisant de préférence ls
) pour imprimer uniquement le <voicepack name>
, dans tous les potentiellement nombreux <language>
sous-répertoires?
Je suis sur Fedora, et ces packs vocaux 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|^$"
L'utilisation de ls
dans ce manoir est généralement désapprouvée car la sortie de ls
est difficile à analyser. Mieux vaut utiliser la commande find
, 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
Cette commande fonctionne en produisant une liste de chemins complets vers des fichiers qui ont exactement 2 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 basename
pour l'analyser:
$ basename /usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
nitech_us_awb_arctic_hts
En mettant tout cela ensemble, nous pouvons faire passer la commande find
chaque répertoire profond de 2 niveaux à la commande basename
. La notation basename {}
est ce qui fait ces conversions de nom de base. Trouver l'appelle via c'est -exec
commutateur.
Le plus simple est
ls -d /usr/share/festival/voices/*/*
Celui-ci est étendu par le shell dans tous les sous-répertoires de /usr/share/festival/voices/
puis au contenu de chacun de ces sous-répertoires.
Si vous voulez seulement descendre à un niveau spécifique comme le suggère votre titre, avec quelques implémentations de find
comme GNU et certains 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 de /usr/share/festival/voices/
à cause de mindepth 2
mais pas plus bas que 3 niveaux plus bas (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.
réponse acceptée fonctionne correctement mais est quelque peu inefficace car il engendre un nouveau processus basename
pour chaque sous-répertoire:
find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
-type d -exec basename {} \;
Lorsque cela est possible, il est préférable d'utiliser des fonctionnalités intégrées à find
pour éviter les frais de processus de génération. find
a une capacité assez étendue pour modifier sa sortie imprimée en utilisant le -printf
action. Le défaut -print
action imprime le chemin entier, mais en utilisant -printf
et une chaîne de format, il est possible de sélectionner des parties du chemin pour l'impression. Pour extraire uniquement la partie du nom de fichier du chemin sans les répertoires principaux (comme le fait basename
), la chaîne de format est %f
. Pour placer une nouvelle ligne après chaque nom de fichier, incluez \n
comme 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
TLDR; pour ceux qui viennent juste ici sur la base du title de cette question; à "Liste des sous-répertoires uniquement n niveau [s] profond": utilisez
find -maxdepth N
où N
est un nombre quelconque.