Bash: pipe 'trova' l'output in 'readarray'


14

Sto cercando di cercare i file utilizzando finde inserirli in un array Bash in modo da poter eseguire altre operazioni su di essi (ad esempio lso su di grepessi). Ma non riesco a capire perché readarraynon stia leggendo l' findoutput mentre viene reindirizzato.

Supponiamo di avere due file nella directory corrente file1.txte file2.txt. Quindi l' findoutput è il seguente:

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

Quindi voglio reindirizzarlo in un array i cui due elementi sono le stringhe "./file1.txt"e "./file2.txt"(senza virgolette, ovviamente).

Ho provato questo, tra le altre cose:

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

0

Come puoi vedere echodall'output, il mio array è vuoto.

Quindi cosa sto facendo esattamente di sbagliato qui? Perché readarraynon leggere findl'output come input standard e inserire quelle stringhe nell'array?

Risposte:


21

Quando si utilizza una pipeline, bash esegue i comandi in subshells. Pertanto, l'array viene popolato, ma in una subshell, quindi la shell padre non ha accesso ad essa.

Usa la sostituzione del processo:

readarray FILES < <(find)

Si noti che non funziona per i file con newline nei loro nomi. In tal caso, è necessaria una sintassi più elaborata:

readarray -d '' < <(find -print0)

3
Per supportare le nuove linee, questo è sufficiente:readarray -d '' < <(find your_args -print0)
VasyaNovikov,

6

La soluzione corretta è:

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

È simile a quello che Greg BashFAQ 020 spiega in dettaglio e questa risposta copre .

Non ha problemi con file con nomi dispari (che non contengono NUL nel nome), con spazi o nuove righe. E il risultato è impostato in un array, che lo rende utile per ulteriori elaborazioni.


Fantastico, questa è una soluzione migliore al problema che stavo cercando di risolvere in primo luogo. +1 non appena il mio rappresentante raggiunge il 15 :)
villapx,

3

readarray può anche leggere da stdin

readarray FILES <<< "$(find . -name "file*")"; echo "${#FILES[@]}"

Questo non funziona con la find -print0protezione da nomi di file "imprevisti".
roaima,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.