Festival хранит данные голосового пакета в следующем примере структуры каталогов:
/usr/share/festival/voices/<language>/<voicepack name>
Какой самый простой однострочный код (предпочтительно с использованием ls
) позволит вывести только <voicepack name>
символы ' во всех потенциально многочисленных <language>
подкаталогах?
решение1
У меня Fedora, и эти голосовые пакеты находятся немного в другом месте:
$ 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
Вы можете просто изменить это следующим образом:
$ ls /usr/share/festival/voices/*/ -1 | grep -vE "/usr|^$"
Используя поиск
Использование ls
в этом manor обычно не приветствуется, поскольку вывод ls
сложно анализировать. Лучше использовать команду find
, например:
$ 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
Подробности поиска и базового имени
Эта команда создает список полных путей к файлам, которые находятся ровно на 2 уровня вложенности относительно данного каталога:
/usr/share/festival/lib/voices
Этот список выглядит так:
$ 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
Но нам нужна последняя часть этих каталогов, листовой узел. Поэтому мы можем использовать basename
для его разбора:
$ basename /usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
nitech_us_awb_arctic_hts
Собрав все вместе, мы можем заставить find
команду передавать каждый 2-уровневый каталог команде basename
. Нотация basename {}
— это то, что делает эти преобразования базовых имен. Find вызывает его через свой -exec
переключатель.
решение2
Самый простой - это
ls -d /usr/share/festival/voices/*/*
Оболочка расширяет его на все подкаталоги, /usr/share/festival/voices/
а затем на содержимое каждого из этих подкаталогов.
Если вы хотите опуститься только до определенного уровня, как следует из вашего заголовка, с некоторыми реализациями вроде find
GNU и некоторыми BSD:
find /usr/share/festival/voices/ -mindepth 2 -maxdepth 3 -type d
Это найдет все каталоги ( -type d
), которые находятся в подкаталоге из- /usr/share/festival/voices/
за того, что mindepth 2
, но не глубже, чем на 3 уровня вниз ( maxdepth 3
). Из 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.
решение3
Theпринятый ответработает правильно, но несколько неэффективно, поскольку порождает новый basename
процесс для каждого подкаталога:
find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
-type d -exec basename {} \;
Когда это возможно, предпочтительнее использовать встроенные функции, find
чтобы избежать расходов на порождение процессов. find
имеет довольно обширные возможности для изменения своего печатного вывода с помощью -printf
действия. -print
Действие по умолчанию печатает весь путь, но с помощью -printf
и строки формата можно выбрать части пути для печати. Чтобы извлечь только часть имени файла из пути без ведущих каталогов (как basename
это делается), строка формата будет %f
. Чтобы поместить новую строку после каждого имени файла, включите \n
следующее:
$ 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
решение4
Для тех, кто использует bash и ищет что-то простое, используя ls:
ls -d $PWD/*
При создании псевдонима (в ~/.bash_aliases или где-либо еще) обязательно используйте одинарные кавычки:
alias ldf='ls -d $PWD/*'
Если не заключить его в кавычки, оболочка попытается выполнить ls.
Двойные кавычки создадут псевдоним со значением $PWD на момент создания псевдонима.
Вы можете использовать $(pwd), если предпочитаете, но я не вижу смысла в создании дочерней оболочки, когда bash предоставляет вам $PWD.