¿Cómo escribo un script bash que atraviesa cada directorio dentro de un directorio parent_directory y ejecuta un comando en cada directorio ?
La estructura del directorio es la siguiente:
parent_directory (el nombre puede ser cualquier cosa, no sigue un patrón)
- 001 (los nombres de directorio siguen este patrón)
- 0001.txt (los nombres de archivo siguen este patrón)
- 0002.txt
- 0003.txt
- 002
- 0001.txt
- 0002.txt
- 0003.txt
- 0004.txt
- 003
- 0001.txt
El número de directorios es desconocido.

cd "$d"sería mejor ya que se transfiere a situaciones en las que el comodín coincide con los archivos cuyos nombres contienen espacios en blanco y / o metacaracteres de shell.for f in foo bar; do cat "$f"/*.txt; done >outputes funcionalmente equivalente acat foo/*.txt bar/*.txt >output. Sin embargo,lses un comando que produce resultados ligeramente diferentes dependiendo de cómo le pase los argumentos; Del mismo modo, ungrepowcque genera un nombre de archivo relativo será diferente si lo ejecuta desde un subdirectorio (pero a menudo, desea evitar entrar en un subdirectorio precisamente por esa razón).Esta respuesta publicada por Todd me ayudó.
El
\( ! -name . \)evita ejecutar el comando en el directorio actual.fuente
find FOLDER* -maxdepth 0 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd" \;-exec bash -c 'cd "$0" && pwd' {} \;ya que algunos directorios contenían comillas simples y algunas comillas dobles.-mindepth 1pwddirectamente?disd(){find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c 'cd "{}" && "$@"' \;}no trabajo.Si está utilizando GNU
find, puede probar el-execdirparámetro, por ejemplo:o (según el comentario de @gniourf_gniourf ):
Nota: Puede usar en
${0#./}lugar de$0arreglar./en el frente.o un ejemplo más práctico:
Si desea incluir el directorio actual, es aún más simple usando
-exec:o usando
xargs:O ejemplo similar sugerido por @gniourf_gniourf :
Los ejemplos anteriores admiten directorios con espacios en su nombre.
O asignando a bash array:
Cambie
.a su nombre de carpeta específico. Si no necesita ejecutar recursivamente, puede usar: en sudirs=(*)lugar. El ejemplo anterior no admite directorios con espacios en el nombre.Entonces, como sugirió @gniourf_gniourf , la única forma adecuada de colocar la salida de find en una matriz sin usar un bucle explícito estará disponible en Bash 4.4 con:
O no es una forma recomendada (que implica el análisis de
ls):El ejemplo anterior ignoraría el directorio actual (según lo solicitado por OP), pero se romperá en los nombres con los espacios.
Ver también:
fuente
finden una matriz sin usar un bucle explícito estará disponible en Bash 4.4 conmapfile -t -d '' dirs < <(find . -type d -print0). Hasta entonces, su única opción es usar un bucle (o diferir la operaciónfind).dirsmatriz; usted podría bucle defindsalida 's (con seguridad), así:find . -type d -print0 | while IFS= read -r -d '' file; do ...; done.IFS,read, da la impresión de una complejidad adicional. Tendré que pensarlo, tal vez haya una forma más fácil de hacerlo.IFSyread(como dices) se convierte en una segunda naturaleza a medida que te acostumbras ... son parte de las formas canónicas e idiomáticas de escribir guiones.find . -type d -execdir echo $(pwd)/{} ';'no hace lo que quiere (el$(pwd)se expande antesfindincluso se ejecuta) ...Puede lograr esto canalizando y luego utilizando
xargs. El problema es que necesita utilizar el-Iindicador que sustituirá a la subcadena en su comando de fiesta con la subcadena aprobada por cada uno de losxargs.Es posible que desee reemplazar
pwdcon cualquier comando que desee ejecutar en cada directorio.fuente
Si se conoce la carpeta de nivel superior, puede escribir algo como esto:
En el $ (JUEGA TANTO COMO QUIERAS); puedes poner tanto código como quieras.
Tenga en cuenta que no "cd" en ningún directorio.
Salud,
fuente
ls" ; en su lugar, podría hacerlofor dir in $YOUR_TOP_LEVEL_FOLDER/*.ls $direxpresiónfuente
Si bien uno de los revestimientos es bueno para un uso rápido y sucio, prefiero a continuación una versión más detallada para escribir scripts. Esta es la plantilla que uso, que se encarga de muchos casos extremos y le permite escribir código más complejo para ejecutar en una carpeta. Puede escribir su código bash en la función dir_command. A continuación, dir_coomand implementa el etiquetado de cada repositorio en git como ejemplo. El resto del script llama a dir_command para cada carpeta en el directorio. También se incluye el ejemplo de iterar solo a través de un conjunto de carpetas determinado.
fuente
No entiendo el formato del archivo, ya que solo quieres recorrer las carpetas ... ¿Estás buscando algo como esto?
fuente
puedes usar
para buscar todos los archivos / directorios en el directorio actual recurrente
De lo que puede canalizar la salida, el comando xargs así
fuente
fuente
cden una subshell.cdpor lo que este código en realidad no hace nada útil.