Bash: canaliza a saída 'find' para 'readarray'

7

Estou tentando pesquisar arquivos usando find e colocar esses arquivos em uma matriz Bash para que eu possa realizar outras operações neles (por exemplo, ls ou grep deles). Mas não consigo entender por que readarray não está lendo a saída find quando é canalizada para ela.

Digamos que eu tenha dois arquivos no diretório atual, file1.txt e file2.txt . Portanto, a saída find é a seguinte:

$ find . -name "file*"
./file1.txt
./file2.txt

Então eu quero canalizar isso em uma matriz cujos dois elementos são as strings "./file1.txt" e "./file2.txt" (sem as aspas, obviamente).

Eu tentei isso, entre algumas outras coisas:

$ declare -a FILES
$ find . -name "file*" | readarray FILES
$ echo "${FILES[@]}"; echo "${#FILES[@]}"

0

Como você pode ver na echo output, minha matriz está vazia.

Então, o que exatamente estou fazendo errado aqui? Por que readarray não está lendo a saída de find como sua entrada padrão e colocando essas sequências na matriz?

    
por villapx 17.02.2016 / 17:16

3 respostas

14

Ao usar um pipeline, o bash executa os comandos em subshells. Portanto, o array é preenchido, mas em um subshell, então o shell pai não tem acesso a ele.

Use a substituição do processo:

readarray FILES < <(find)

Observe que não funciona para arquivos com novas linhas em seus nomes. Se esse for o caso, você precisa de uma sintaxe mais elaborada:

readarray -d '' < <(find -print0)
    
por 17.02.2016 / 17:25
5

A solução correta é:

unset a; declare -a a
while IFS= read -r -u3 -d $'
unset a; declare -a a
while IFS= read -r -u3 -d $'%pre%' file; do
    a+=( "$file" )        # or however you want to process each file
done 3< <(find /tmp -type f -print0)
' file; do a+=( "$file" ) # or however you want to process each file done 3< <(find /tmp -type f -print0)

Isso é semelhante ao que Greg's BashFAQ 020 explica em detalhes e esta resposta cobre .

Não tem problema com arquivos nomeados ímpares (que não contêm NUL no nome), com espaços ou novas linhas. E o resultado é definido em uma matriz, o que o torna útil para processamento adicional.

    
por 17.02.2016 / 19:40
3

readarray também pode ler stdin

readarray FILES <<< "$(find . -name "file*")"; echo "${#FILES[@]}"
    
por 11.11.2016 / 06:08

Tags