0 votos

Los resultados de la búsqueda no pueden encerrarse entre comillas

En Linux, el manejo de los espacios cuando estoy usando los resultados find sólo requiere encerrar la variable entre comillas. Esto no funciona en OS X. Este código, por ejemplo, no funciona:

for file in $(find . -name "*.txt")
do
    ls -l "${file}"
done

Incluso entre comillas, las partes de los nombres de archivo separadas por espacios se tratan como un resultado propio. ¿Cómo puedo arreglar esto?

0 votos

¿Puede utilizar find . -name "*.txt" -exec ls -l {} \; ¿en su lugar?

0 votos

No utilice un for bucle para procesar find resultados, utilice find ... -exec ... en su lugar (y, en casos más complejos, escribir un shell script para que se ejecute el código).

2voto

Desde Trampas de Bash (que también explica detalladamente por qué for file in (find ...); do no funciona):

Al utilizar find utilícelo correctamente por ejemplo, usar -exec

find . -type f -exec some command {} \;

En lugar de ls considerar,

for i in *.mp3; do    # Better! and...
    some command "$i" # ...always double-quote expansions!
done

Los shells POSIX como Bash tienen la característica globbing específicamente para este propósito -- para permitir que el shell expanda los patrones en una lista de nombres de archivos que coincidan. No hay necesidad de interpretar los resultados de una utilidad externa. Como el globbing es el último paso de expansión, cada coincidencia del patrón *.mp3 se expande correctamente a una palabra separada, y no está sujeta a los efectos de una expansión sin comillas. (Si necesita procesar archivos de forma recursiva, consulte UtilizandoFind .)

Pregunta: ¿Qué pasa si no hay *.mp3 -archivos en el directorio actual? Entonces el bucle for se ejecuta una vez, con i="*.mp3" que no es el comportamiento esperado. La solución consiste en comprobar si existe un archivo coincidente:

# POSIX
for i in *.mp3; do
    [ -e "$i" ] || continue
    some command "$i"
done

Observe las comillas alrededor de $i en el cuerpo del bucle anterior.

1voto

Michael Zhou Puntos 167

Su código no funciona en OS X o Linux.

for file in $(find . -name "*.txt")
do
    ls -l "${file}"
done

En primer lugar, el shell realiza la expansión de la sustitución del comando $(find . -name "*.txt") Los resultados se asemejan a los siguientes file with spaces\nanother file with spaces y así sucesivamente. Ahora, el shell realiza word spitting basado en el valor de IFS - el separador de campo interno. El valor suele ser espacio en blanco, tabulador y nueva línea.

Ejecuta el siguiente código:

for file in $(find . -name "*.txt")
do
    echo "${file}"
done

Ahora vamos a cambiar el IFS a sólo el carácter de nueva línea.

IFS='
'
for file in $(find . -name "*.txt")
do
    ls -l -- "${file}"
done

Tu código funcionará aunque te aconsejo que no cambies IFS y encontrar soluciones alternativas.

Tanto GNU find como BSD find son muy robustos y pueden manejar nombres de archivos con espacios. Puede evitar el bucle y obtener resultados similares con una sola línea

find . -name "*.txt" -ls

1 votos

1. Te fuiste = de IFS' esa línea debería ser IFS=' . 2. No hay nada malo en cambiar IFS si se hace correctamente, es decir, fijar la corriente IFS a una variable, modificar IFS para adaptarse a la necesidad en el código y luego restablecerlo de la variable y continuar. 3. Además, mientras find . -name "*.txt" -ls sí funciona, pero no produce el mismo resultado esperado de la ejecución de ls -l por sí mismo y por eso sugerí, en mi comentario a Melab, utilizar find . -name "*.txt" -exec ls -l {} \; en lugar de un bucle completo.

0 votos

Además, si está cambiando IFS para que sea igual a una nueva línea, considere escribirlo como IFS=$'\n'

0 votos

@user556068 ¿Y qué ventajas tiene ansi quoting sobre los otros métodos de cambiar IFS a newline?

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X