Listar subdirectorios solo a n niveles de profundidad

Listar subdirectorios solo a n niveles de profundidad

Festival almacena los datos del paquete de voz en la siguiente estructura de directorio de ejemplo:

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

¿Cuál es el resumen más simple (preferiblemente usando ls) para imprimir solo los 's, en todos los subdirectorios <voicepack name>potencialmente numerosos ?<language>

Respuesta1

Estoy en Fedora y estos paquetes de voz están en una ubicación ligeramente diferente:

$ 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

Puedes modificar esto así:

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

Usando buscar

El uso lsen esta mansión suele estar mal visto porque el resultado lses difícil de analizar. Es mejor usar el findcomando, así:

$ 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

Detalles de búsqueda y nombre base

Este comando funciona generando una lista de rutas completas a archivos que tienen exactamente 2 niveles de profundidad con respecto a este directorio:

/usr/share/festival/lib/voices

Esta lista se ve así:

$ 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

Pero queremos la última parte de estos directorios, el nodo hoja. Entonces podemos utilizar basenamepara analizarlo:

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

Poniéndolo todo junto, podemos hacer que el findcomando pase cada directorio de 2 niveles de profundidad al basenamecomando. La notación basename {}es lo que realiza estas conversiones de nombres base. Find lo llama a través de su -execinterruptor.

Respuesta2

Lo más fácil es

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

El shell lo expande a todos los subdirectorios /usr/share/festival/voices/y luego al contenido de cada uno de esos subdirectorios.

Si solo desea descender a un nivel específico como sugiere el título, con algunas implementaciones de findGNU y algunas BSD:

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

Eso encontrará todos los directorios ( -type d) que están en un subdirectorio de /usr/share/festival/voices/debido a mindepth 2pero que no están a más de 3 niveles hacia abajo ( 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.

Respuesta3

Elrespuesta aceptadafunciona correctamente pero es algo ineficiente porque genera un nuevo basenameproceso para cada subdirectorio:

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

Cuando sea posible, es preferible utilizar funciones integradas findpara evitar el gasto de los procesos de generación. findtiene una capacidad bastante amplia para modificar su salida impresa utilizando la -printfacción. La -print acción predeterminada imprime la ruta completa, pero usando -printfuna cadena de formato es posible seleccionar partes de la ruta para imprimir. Para extraer solo la parte del nombre de archivo de la ruta sin los directorios principales (como basename lo hace), la cadena de formato es %f. Para colocar una nueva línea después de cada nombre de archivo, incluya \nlo siguiente:

$ 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

Respuesta4

Para alguien que usa bash y busca algo simple simplemente usando ls:

ls -d $PWD/*

Al crear un alias (en ~/.bash_aliases o donde sea), asegúrese de usar comillas simples:

alias ldf='ls -d $PWD/*'

Si no lo cita, el shell intentará ejecutar ls.

Entre comillas dobles se creará el alias con el valor de $PWD en el momento del alias.

Podrías usar $(pwd) si lo prefieres, pero no veo el sentido de generar un sub-shell cuando bash te proporciona $PWD.

información relacionada