Reputation: 465
The following contrived example works:
$ while read -r line; do echo $line; done < <(ls -al *.js)
...
The following, however, gives an error:
$ while read -r line; do echo $line; done < <(ls -al {package.json,package-lock.json})
-bash: 0: ambiguous redirect
despite the fact that what is inside the process substitution works fine:
$ ls -al {package.json,package-lock.json}
-rw-r--r-- 1 me staff 764K Apr 19 10:23 package-lock.json
-rw-r--r-- 1 me staff 10K Apr 19 10:23 package.json
Why is that?
Upvotes: 3
Views: 248
Reputation: 125788
This looks like a bug (or at least oddity) in bash v3, but it's fixed in v4. What's happening is that the brace expansion ({package.json,package-lock.json}
) is being applied to the entire process substitution, not just an argument within it. Here's a simplified example I'll use to demo what's going on:
$ cat < <(echo {a,b})
-bash: 0: ambiguous redirect
Let's try some variants of this:
$ cat <(echo {a,b}) # This works, sort of... each arg winds up on a separate line
a
b
$ echo <(echo {a,b}) # echo shows *two* different process substitutions are being done
/dev/fd/63 /dev/fd/62
$ grep -H . <(echo {a,b}) # This prints where it gets each line, showing it gets one letter/line from each substitution
/dev/fd/63:a
/dev/fd/62:b
...so what it looks like is that <(echo {a,b})
is getting brace-expanded to <(echo a) <(echo b)
instead of <(echo a b)
. This works with cat
and grep
because they accept multiple input files, but the <
redirect can only take one input file (so you get an "ambiguous redirect" error).
This seems to be fixed in bash v4 (I've tested in v4.2.10 and 4.4.19):
$ echo $BASH_VERSION
4.4.19(1)-release
$ cat < <(echo {a,b})
a b
$ cat <(echo {a,b})
a b
$ echo <(echo {a,b})
/dev/fd/63
Upvotes: 4