Estoy tratando de construir una matriz en bash de los nombres de archivo de mi cámara:
FILES=(2011-09-04 21.43.02.jpg
2011-09-05 10.23.14.jpg
2011-09-09 12.31.16.jpg
2011-09-11 08.43.12.jpg)
Como puede ver, hay un espacio en el medio de cada nombre de archivo.
Intenté poner cada nombre entre comillas y escapar del espacio con una barra diagonal inversa, ninguno de los cuales funciona.
Cuando intento acceder a los elementos de la matriz, continúa tratando el espacio como el elemento delimitador.
¿Cómo puedo capturar correctamente los nombres de archivo con un espacio dentro del nombre?
FILES[0] = ...
? (Editar: acabo de hacerlo; no funciona. Interesante).find . -maxdepth 1 -type f -iname \*.$1 -printf '%f\n'
); para el elemento en $ {array [@]}; hacer echo $ elemento; hechoRespuestas:
Creo que el problema podría deberse en parte a cómo está accediendo a los elementos. Si hago un simple
for elem in $FILES
, experimento el mismo problema que tú. Sin embargo, si accedo a la matriz a través de sus índices, funciona así si agrego los elementos numéricamente o con escapes:Cualquiera de estas declaraciones de
$FILES
debería funcionar:o
o
fuente
echo "${FILES[$i]}"
). No importaecho
, pero lo será para cualquier cosa que lo use como nombre de archivo.for f in "${FILES[@]}"
.#
símbolo sharp ( ) en lafor ((i = 0; i < ${#FILES[@]}; i++))
declaración?Debe haber algo mal con la forma en que accede a los elementos de la matriz. Así es como se hace:
Desde la página de manual de bash :
Por supuesto, también debe usar comillas dobles al acceder a un solo miembro
fuente
expands to a single word with the value of each array member separated by the first character of the IFS special variable
for elem in "${files[@]}"
mientras lo hayan hechofor elem in ${files[@]}
, por lo que los espacios confunden la expansión y los intentos que se ejecutan en las palabras individuales.Debe usar IFS para detener el espacio como delimitador de elementos.
Si quieres separar en base a. entonces simplemente haga IFS = "." Espero que te ayude :)
fuente
IFS=""
antes de la construcción de la matriz .Estoy de acuerdo con los demás en que es probable que el problema sea cómo accedes a los elementos. Citar los nombres de archivo en la asignación de matriz es correcto:
El uso de comillas dobles alrededor de cualquier matriz del formulario
"${FILES[@]}"
divide la matriz en una palabra por elemento de matriz. No hace ninguna división de palabras más allá de eso.El uso
"${FILES[*]}"
también tiene un significado especial, pero une los elementos de la matriz con el primer carácter de $ IFS, lo que da como resultado una palabra, que probablemente no sea lo que desea.Usando un desnudo
${array[@]}
o${array[*]}
sujetos el resultado de esa expansión para una mayor división de palabras, por lo que terminará con palabras divididas en espacios (y cualquier otra cosa$IFS
) en lugar de una palabra por elemento de matriz.Usar un estilo C para el bucle también está bien y evita preocuparse por la división de palabras si no lo tiene claro:
fuente
Escapando de las obras.
Salida:
Citar las cadenas también produce la misma salida.
fuente
Si tuviera su matriz así: #! / Bin / bash
Obtendrías:
No sé por qué, pero el bucle divide los espacios y los coloca como un elemento individual, incluso si lo rodea con comillas.
Para evitar esto, en lugar de llamar a los elementos de la matriz, llama a los índices, que toman la cadena completa que está entre comillas. ¡Debe estar entre comillas!
Entonces obtendrás:
fuente
No es exactamente una respuesta al problema de cita / escape de la pregunta original, pero probablemente algo que realmente hubiera sido más útil para la operación:
Donde, por supuesto, la expresión tendría que adoptarse según el requisito específico (por ejemplo,
*.jpg
para todos o2001-09-11*.jpg
solo para las imágenes de un día determinado).fuente
Otra solución es usar un ciclo "while" en lugar de un ciclo "for":
fuente
Si no está atascado en el uso
bash
, el manejo diferente de espacios en los nombres de archivos es uno de los beneficios de la concha de pescado . Considere un directorio que contiene dos archivos: "a b.txt" y "b c.txt". Aquí hay una suposición razonable al procesar una lista de archivos generados a partir de otro comandobash
, pero falla debido a los espacios en los nombres de archivo que experimentó:Con
fish
, la sintaxis es casi idéntica, pero el resultado es lo que cabría esperar:Funciona de manera diferente porque fish divide la salida de comandos en nuevas líneas, no espacios.
Si tiene un caso en el que desea dividir en espacios en lugar de líneas nuevas,
fish
tiene una sintaxis muy legible para eso:fuente
Solía restablecer el valor de IFS y la reversión cuando terminaba.
Posible salida del bucle:
fuente