Eu só quero obter todos os arquivos em um determinado diretório em uma matriz bash (supondo que nenhum dos arquivos tenha uma nova linha no nome):
Assim:
myarr=()
find . -maxdepth 1 -name "mysqldump*" | mapfile -t myarr; echo "${myarr[@]}"
Resultado vazio!
Se eu usar a maneira indireta de usar um arquivo, temporário ou não:
myarr=()
find . -maxdepth 1 -name "mysqldump*" > X
mapfile -t myarray < X
echo "${myarray[@]}"
Resultado!
Mas por que não mapfile
lê corretamente de um cachimbo?
find
emapfile
aqui em tudo e não apenas simplesmentemyarr=(mysqldump*)
? Isso funcionará mesmo com nomes de arquivos com espaços e novas linhas.nullglob
opção (shopt -s nullglob
) paramyarr=(mysqldump*)
não terminar com a matriz('mysqldump*')
caso nenhum arquivo corresponda.Respostas:
De
man 1 bash
:Tais subshells herdam variáveis do shell principal, mas são independentes. Isso significa que
mapfile
no seu comando original opera por conta própriamyarr
. Entãoecho
(estando fora do tubo) imprime vaziomyarr
(que é o shell principalmyarr
).Este comando funciona de maneira diferente:
Nesse caso,
mapfile
eecho
opere da mesma formamyarr
(que não é o shell principalmyarr
).Para alterar o shell principal,
myarr
você deve executarmapfile
exatamente no shell principal. Exemplo:fonte
O Bash executa os comandos de um pipeline em um ambiente subshell, para que quaisquer atribuições de variáveis etc. que ocorram nele não sejam visíveis para o restante do shell.
O Dash (Debian
/bin/sh
) e o busyboxsh
são semelhantes, enquanto o zsh e o ksh executam a última parte no shell principal. No Bash, você podeshopt -s lastpipe
fazer o mesmo, mas só funciona quando o controle de trabalho está desativado, portanto, não em shells interativos por padrão.Assim:
(
read
emapfile
tem o mesmo problema.)Como alternativa (e conforme mencionado por Attie), use a substituição de processo , que funciona como um pipe generalizado, e é suportada no Bash, ksh e zsh.
O POSIX deixa não especificado se as partes de um pipeline são executadas em subconchas ou não, portanto, não se pode realmente dizer que alguma das conchas estaria "errada" nisso.
fonte
set +m; shopt -s lastpipe; x=a; echo b | read x; echo $x; set -m
Como Kamil apontou, cada elemento no pipeline é um processo separado.
Você pode usar a seguinte substituição processo para obter
find
a correr em um processo diferente, com amapfile
invocação restante em sua intérprete atual, permitindo o acesso amyarr
tarde:b < <( a )
agirá de maneira semelhantea | b
em termos de como o pipeline é conectado - a diferença é queb
é executado " aqui ".fonte