2 votos

¿Cómo puedo detener la división de palabras en el bucle for de bash?

Cuando ejecuto el comando de abajo:

mdfind -name iMazing

Obtengo la siguiente salida:

/Users/apple/Library/Application Support/MobileSync/Backup/iMazing.Versions
/Users/apple/Library/Application Support/com.DigiDNA.iMazing2Mac

Quiero ejecutar un bucle for a para borrar estos dirs.

Antes de hacerlo he probado con ls :

for i in $(mdfind -name); do ls "$i"; done

La salida:

ls: /Users/apple/Library/Application: No such file or directory
ls: Support/MobileSync/Backup/iMazing.Versions: No such file or directory
ls: /Users/apple/Library/Application: No such file or directory
ls: Support/com.DigiDNA.iMazing2Mac: No such file or directory

Como puede ver, la división de palabras se ha producido debido al espacio en Application Support

He probado las siguientes variaciones:

"${i}"

Escapar de las comillas:

"\"$i"\"

"\"${i}"\"

sin éxito, ¿alguna idea?

EDITAR:

Así que IFS no importa, ¿qué está pasando?:

 kn: (master)  
   IFS=; for i in $(mdfind -name iMazing); do ls "$i"; done
ls: /Users/apple/Library/Application Support/MobileSync/Backup/iMazing.Versions
/Users/apple/Library/Application Support/com.DigiDNA.iMazing2Mac: No such file or directory
  kn: (master)  
   while IFS= read -r i; do ls "$i"; done < <(mdfind -name iMazing)
Blueprints  Readme.txt  Temp        Trash       Versions
com.microsoft.appcenter
  kn: (master)  
   while read -r i; do ls "$i"; done < <(mdfind -name iMazing)
Blueprints  Readme.txt  Temp        Trash       Versions
com.microsoft.appcenter

7voto

siva Puntos 23

El problema no es la cita de $i - que es demasiado tarde.

El bucle for ya ha dividido la entrada por espacios, por lo que cada iteración del bucle for está recibiendo uno de los cuatro componentes mostrados en los errores. Es necesario arreglar el bucle en su lugar.

Esto se puede hacer estableciendo el IFS, el separador interno de campos, como una nueva línea.

IFS=$'\n'; for i in $(mdfind -name iMazing); do ls "$i"; done

IFS es la forma en que bash determina cómo dividir la entrada. Por defecto, incluye el espacio, por lo que cada espacio en cada línea de la entrada se divide en dos entradas, junto a las nuevas líneas existentes, causando 4 bucles en lugar de 2. Establecer IFS a nueva línea sólo desactiva esta división por espacio, preservando cada línea de entrada sin división adicional.


Una forma potencialmente preferible de hacer un bucle sobre líneas de salida está utilizando read -r line :

while IFS= read -r line; do echo rm -R "$line"; done < <(mdfind -name iMazing)

Unix.SE tiene un buen desglose de IFS= read -r line :

6voto

Nate Puntos 220

Si sólo quieres pasar los resultados a un único comando (no ejecutar una secuencia de comandos, o algo complejo como eso), puedes usar xargs . Si el comando puede tomar un montón de nombres de archivo a la vez, utilice algo como esto:

mdfind -0 -name iMazing | xargs -0 ls

El -0 hacen que los comandos utilicen bytes nulos como delimitadores; como éstos no pueden aparecer en los nombres de archivo, esto está a salvo de todas las confusiones habituales.

Nota: si vas a usar esto con algo peligroso, como rm Recomiendo ejecutarlo con algo seguro, como ls para asegurarte de que va a hacer lo que quieres. (Y... tienes una buena copia de seguridad, ¿verdad?) Si quieres ser realmente cuidadoso, añade el -p (después de xargs pero antes del comando a ejecutar) e imprimirá el comando y pedirá confirmación antes de ejecutarlo.

Además, si el comando no puede tomar un montón de nombres de archivo a la vez, añade -n 1 (de nuevo, después de xargs pero antes del comando).

3voto

Mark Puntos 6

Si instalas una versión de bash >= 4.0 (por ejemplo, con Homebrew), puedes hacerlo:

mapfile -t files < <(mdfind -name iMazing)

que lee el líneas de la salida de mdfind en la matriz de "archivos". A continuación,

for file in "${files[@]}"; do ls "$file"; done

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