Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"< <(command-here)" shell idiom resulting in "redirection unexpected"

This command works fine:

$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)

However, I don't understand how exactly stable is passed as a parameter to the shell script that is downloaded by curl. That's the reason why I fail to achieve the same functionality from within my own shell script - it gives me ./foo.sh: 2: Syntax error: redirection unexpected:

$ cat foo.sh 
#!/bin/sh
bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)

So, the questions are: how exactly this stable param gets to the script, why are there two redirects in this command, and how do I change this command to make it work inside my script?

like image 773
Oleg Mikheev Avatar asked Mar 13 '12 14:03

Oleg Mikheev


1 Answers

Regarding the "redirection unexpected" error:

That's not related to stable, it's related to your script using /bin/sh, not bash. The <() syntax is unavailable in POSIX shells, which includes bash when invoked as /bin/sh (in which case it turns off nonstandard functionality for compatibility reasons).

Make your shebang line #!/bin/bash.

Understanding the < <() idiom:

To be clear about what's going on -- <() is replaced with a filename which refers to the output of the command which it runs; on Linux, this is typically a /dev/fd/## type filename. Running < <(command), then, is taking that file and directing it to your stdin... which is pretty close the behavior of a pipe.

To understand why this idiom is useful, compare this:

read foo < <(echo "bar")
echo "$foo"

to this:

echo "bar" | read foo
echo "$foo"

The former works, because the read is executed by the same shell that later echoes the result. The latter does not, because the read is run in a subshell that was created just to set up the pipeline and then destroyed, so the variable is no longer present for the subsequent echo.

Understanding bash -s stable:

bash -s indicates that the script to run will come in on stdin. All arguments, then, are fed to the script in the $@ array ($1, $2, etc), so stable becomes $1 when the script fed in on stdin is run.

like image 172
Charles Duffy Avatar answered Oct 24 '22 17:10

Charles Duffy