Solo quiero obtener todos los archivos en un determinado directorio en una matriz bash (suponiendo que ninguno de los archivos tenga una nueva línea en el nombre):
Entonces:
myarr=()
find . -maxdepth 1 -name "mysqldump*" | mapfile -t myarr; echo "${myarr[@]}"
Resultado vacío!
Si hago la forma indirecta de usar un archivo, temporal o de otra manera:
myarr=()
find . -maxdepth 1 -name "mysqldump*" > X
mapfile -t myarray < X
echo "${myarray[@]}"
¡Resultado!
Pero, ¿por qué no mapfile
lee correctamente de una tubería?
find
ymapfile
aquí en absoluto y no simplementemyarr=(mysqldump*)
? Esto incluso funcionará con nombres de archivos con espacios y líneas nuevas.nullglob
opción (shopt -s nullglob
) paramyarr=(mysqldump*)
no terminar con la matriz('mysqldump*')
en caso de que no coincidan los archivos.Respuestas:
De
man 1 bash
:Tales subcapas heredan variables de la coraza principal pero son independientes. Esto significa que
mapfile
en su comando original opera por sí solomyarr
. Luegoecho
(estando fuera de la tubería) imprime vacíomyarr
(que es el caparazón principalmyarr
).Este comando funciona de manera diferente:
En este caso
mapfile
yecho
operar en el mismomyarr
(que no es el shell principalmyarr
).Para cambiar el shell principal,
myarr
debe ejecutarmapfile
exactamente en el shell principal. Ejemplo:fuente
Bash ejecuta los comandos de una tubería en un entorno de subshell, por lo que cualquier asignación de variables, etc. que tenga lugar dentro de ella no será visible para el resto del shell.
Dash (Debian's
/bin/sh
) así como busybox'ssh
son similares, mientras que zsh y ksh ejecutan la última parte en el shell principal. En Bash, puedeshopt -s lastpipe
hacer lo mismo, pero solo funciona cuando el control de trabajo está deshabilitado, por lo que no se encuentra en shells interactivos de forma predeterminada.Entonces:
(
read
ymapfile
tienen el mismo problema)Alternativamente (y como lo menciona Attie), use la sustitución de procesos , que funciona como una tubería generalizada y es compatible con Bash, ksh y zsh.
POSIX lo deja sin especificar si las partes de una tubería se ejecutan en subcapas o no, por lo que realmente no se puede decir que cualquiera de las cáscaras estaría "mal" en esto.
fuente
set +m; shopt -s lastpipe; x=a; echo b | read x; echo $x; set -m
Como Kamil ha señalado, cada elemento en la tubería es un proceso separado.
Se puede utilizar la siguiente sustitución proceso para conseguir
find
que se ejecute en un proceso diferente, con lamapfile
invocación que queda en su intérprete actual, permitiendo el acceso amyarr
después:b < <( a )
actuará de manera similara | b
en términos de cómo está conectada la tubería; la diferencia es queb
se ejecuta " aquí ".fuente