He escrito el siguiente script para ejecutarlo en Git Bash en Windows 7:
#!/usr/bin/env sh
for logfile in `find -name "*.log" -o -name "*.err" -o -name "*.out"`
do
echo $logfile
grep "api/" "$logfile"
done
El problema es que grep se ahoga cuando un nombre de archivo tiene un espacio. Pensé que las comillas dobles deberían solucionar eso, pero no coopera.
¿Ideas?
Respuesta1
Solución 1
La solución más cercana es usar find
with -print0
y leer el resultado con while read …
:
find -name "*.log" -o -name "*.err" -o -name "*.out" -type f -print0 | while IFS= read -r -d '' logfile; do
...
Continúe usando "$logfile"
comillas, como siempre debe hacerlo cuando usa variables.
Solución 2
Otra solución sería no usarla find
en absoluto y simplemente dejar que grep
se ejecute en varios archivos:
shopt -s nullglob
shopt -s globstar
grep "api/" **/*.log **/*.err **/*.out
Aquí, globstar
se habilita la coincidencia recursiva de directorios con **
. Debe configurar nullglob
para evitar errores si una de estas extensiones de archivo no existe.
Sin embargo, esto sólo funciona para un conjunto limitado de archivos, ya que puede alcanzar la longitud máxima de los argumentos de la línea de comando.
¿Por qué ocurre el error?
Nunca debe ejecutar for
la salida de find
(o ls
, o cualquier otra función que genere nombres de archivos con espacios en blanco). LeerEste artículopara obtener más información sobre por qué esto es un problema y qué se puede hacer para resolverlo.
En resumen, Bash divide los argumentos por espacios en blanco. Imagine que tiene tres archivos, a
y foo bar
, b
luego la línea se evaluaría como:
for logfile in a foo bar b; do
Obviamente, Bash se configurará logfile
en a
, foo
, bar
y b
, que no es lo que quería. Si pudiera especificar manualmente la entrada a for
, incluiría estos nombres de archivos entre comillas para resolver el problema.
Para hacer esto automáticamente, la solución es delimitar estos nombres de archivos con un NUL
carácter (que es lo que -print0
hace la opción) y luego dividir la salida en función de ese NUL
carácter nuevamente (que es lo que hace el -d ''
in read
).