Los resultados de la búsqueda no se pueden encapsular entre comillas

0

En Linux, el manejo de espacios cuando estoy usando los resultados find solo requiere incluir 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 su propio resultado. ¿Cómo soluciono esto?

    
pregunta Melab 29.08.2016 - 19:13

2 respuestas

2

De Bash Pitfalls (que también explica en detalle por qué for file in (find ...); do doesn no funciona):

  

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

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

En lugar de ls considere,

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

Los shells POSIX, como Bash, tienen la característica de globo específicamente para este propósito: para permitir que el shell expanda los patrones en una lista de nombres de archivos coincidentes. No es necesario interpretar los resultados de una utilidad externa. Debido a que el globo es el último paso de la 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 UsingFind .)

     

Pregunta: ¿Qué sucede si no hay *.mp3 -files en el directorio actual? Luego, el bucle for se ejecuta una vez, con i="*.mp3" , ¡que no es el comportamiento esperado! La solución es probar si hay un archivo coincidente:

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

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

    
respondido por el nohillside 30.08.2016 - 20:41
1

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

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

Primero, el shell realiza la expansión del comando de sustitución $(find . -name "*.txt") Los resultados se parecen 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 cambiemos el IFS a solo el carácter de nueva línea.

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

Su código funcionará, aunque le aconsejo que no cambie IFS y encuentre 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 línea

find . -name "*.txt" -ls
    
respondido por el fd0 29.08.2016 - 23:24

Lea otras preguntas en las etiquetas