/ / Bash find: enumera todos los archivos con prefijos de un bucle for - bash

Bash find: enumera todos los archivos con prefijos de un bucle for - bash

Aquí hay una pequeña [pero completa] parte de mi fiestascript que encuentra y genera todos los archivos en mydir si tienen el prefijo de una matriz almacenada. Lo extraño que noto es que este script funciona perfectamente si elimino el "-maxdepth 1 -name" del script; de lo contrario, solo me da los archivos con el prefijo del primer elemento de la matriz.

Sería de gran ayuda si alguien me explicara esto. Lo siento de antemano si hay algo obviamente tonto que estoy haciendo. Soy relativamente nuevo en las secuencias de comandos.

#!/bin/sh
DIS_ARRAY=(A B C D)
echo "Array is : "
echo ${DIS_ARRAY[*]}
for dis in $DIS_ARRAY
do
IN_FILES=`find /mydir  -maxdepth 1 -name "$dis*.xml"`
for file in $IN_FILES
do
echo $file
done
done

Salida:

/mydir/Abc.xml
/mydir/Ab.xml
/mydir/Ac.xml

Rendimiento esperado:

/mydir/Abc.xml
/mydir/Ab.xml
/mydir/Ac.xml
/mydir/Bc.xml
/mydir/Cb.xml
/mydir/Dc.xml

Respuestas

2 para la respuesta № 1

El bucle está roto de cualquier manera. La razón por la cual

IN_FILES=`find mydir  -maxdepth 1 -name "$dis*.xml"`

trabaja, mientras que

IN_FILES=`find mydir "$dis*.xml"`

no es porque en el primero, ha especificado -name. En el segundo find está enumerando todos los archivos en mydir. Si cambia el segundo a

IN_FILES=`find mydir -name "$dis*.xml"`

verá que el bucle no funciona.

Como se menciona en los comentarios, la sintaxis que está utilizando actualmente $DIS_ARRAY solo te dará el primer elemento de la matriz.

Intenta cambiar tu ciclo a esto:

for dis in "${DIS_ARRAY[@]}"

En este caso, las comillas dobles no son necesarias, por lo que puede hacer lo siguiente:

for dis in ${DIS_ARRAY[@]}

Las comillas son necesarias si su matriz contenía espacios, por ejemplo, si desea recorrer la matriz arr=( "a a" "b b" ).

Aquí hay una prueba que muestra lo que está sucediendo:

#!/bin/sh

arr=("a a" "b b")

echo using "$arr"
for i in $arr; do echo $i; done
echo using "${arr[@]}"
for i in ${arr[@]}; do echo $i; done
echo using ""${arr[@]}""
for i in "${arr[@]}"; do echo $i; done

salida:

using $arr
a
a
using ${arr[@]}
a
a
b
b
using "${arr[@]}"
a a
b b

Mira esto pregunta relacionada para mas detalles.


1 para la respuesta № 2

La respuesta de @TomFenech resuelve su problema, pero permítame sugerirle otras mejoras:

#!/usr/bin/env bash

DIS_ARRAY=(A B C D)
echo "Array is : "
echo ${DIS_ARRAY[*]}
for dis in "${DIS_ARRAY[@]}"
do
for file in "/mydir/$dis"*.xml
do
if [ -f "$file" ]; then
echo "$file"
fi
done
done
  • Tus referencias de línea shebang sh, pero tu pregunta está etiquetada bash - a menos que necesite cumplimiento POSIX, use un bash línea shebang para aprovechar todo eso bash tiene que ofrecer
  • Para hacer coincidir los archivos ubicados directamente en un directorio dado (es decir, si no necesita recorrer todo subárbol), use un globo (patrón de nombre de archivo) y confíe en la expansión del nombre de ruta como en mi código anterior - no es necesario find y la sustitución de comandos.
  • Tenga en cuenta que el carácter comodín. * no está entre comillas para garantizar la expansión del nombre de ruta.
  • Advertencia: si no se encuentran archivos coincidentes, el globo no se modifica (suponiendo que nullglob la opción de shell está desactivada, que es la opción predeterminada), por lo que el bucle se ingresa una vez, con un nombre de archivo no válido (el globo no expandido), de ahí el [ -f "$file" ] condicional para asegurar que se encontró una coincidencia real (como un aparte: usando bashisms, podría usar [[ -f $file ]] en lugar).