Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I stuck with an strange behaviour of readarray command.

The man bash states:

     Read lines from the standard input into the indexed array variable array

but these scripts don't work (array is empty):

unset arr; (echo a; echo b; echo c) | readarray arr; echo ${#arr[@]}
unset arr; cat /etc/passwd | readarray arr;  echo ${#arr[@]}

And these work:

unset arr; readarray arr < /etc/passwd ;  echo ${#arr[@]}
unset arr; mkfifo /tmp/fifo; (echo a; echo b; echo c) > /tmp/fifo & mapfile arr < /tmp/fifo ; echo ${#arr[@]}

What wrong with pipe?

share|improve this question
up vote 7 down vote accepted

Maybe try:

unset arr
printf %s\\n a b c | {
    readarray arr
    echo ${#arr[@]}

I expect it will work, but the moment you step out of that last { shell ; } context at the end of the |pipeline there you'll lose your variable value. This is because each of the |separate | processes within a |pipeline is executed in a (subshell). So your thing doesn't work for the same reason:

( arr=( a b c ) ) ; echo ${arr[@]}

...doesn't - the variable value was set in a different shell process than the one in which you call on it.

share|improve this answer
Yes. You are right. I forgot about subshells. Thank you. – dchirikov Jun 9 '14 at 11:58

To ensure the readarray command executes in the current shell, either use process substitution in place of the pipeline:

readarray arr < <( echo a; echo b; echo c )

or (if bash 4.2 or later) use the lastpipe shell option:

shopt -s lastpipe
( echo a; echo b; echo c ) | readarray arr
share|improve this answer
Cool. This works, but what exactly is process substitution? And what does it mean to have < < 2 arrows? – CMCDragonkai Jul 1 '14 at 2:15
See the bash man page. In short, it's syntax for treating a pipeline as a file descriptor. < <(...) means to redirect input (the first <) from the output of the command inside <(...). Similary, > >(...) would pass standard output to the standard input of the pipeline inside >(...). You don't necessarily need to use redirection with process substitution. cat <( echo a b c ) works as well. – chepner Jul 1 '14 at 14:40

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.