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 mapfilelee correctamente de una tubería?

findymapfileaquí en absoluto y no simplementemyarr=(mysqldump*)? Esto incluso funcionará con nombres de archivos con espacios y líneas nuevas.nullglobopció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
mapfileen 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
mapfileyechooperar en el mismomyarr(que no es el shell principalmyarr).Para cambiar el shell principal,
myarrdebe ejecutarmapfileexactamente 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'sshson similares, mientras que zsh y ksh ejecutan la última parte en el shell principal. En Bash, puedeshopt -s lastpipehacer 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:
(
readymapfiletienen 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 -mComo Kamil ha señalado, cada elemento en la tubería es un proceso separado.
Se puede utilizar la siguiente sustitución proceso para conseguir
findque se ejecute en un proceso diferente, con lamapfileinvocación que queda en su intérprete actual, permitiendo el acceso amyarrdespués:b < <( a )actuará de manera similara | ben términos de cómo está conectada la tubería; la diferencia es quebse ejecuta " aquí ".fuente