I'm trying to run a script remotely and use its standard output to populate a variable. I'm doing this to avoid temporary files.
Here's the pattern I'm trying:
var=$(bash <(curl -fsSkL http://remote/file.sh))
echo "var=${var}"
I'm testing this pattern without curl
using cat
:
var=$(bash <(cat ./local/file.sh))
echo "var=${var}"
This should be the same as far as syntax is concerned. ./local/file.sh
contains echo hello
, so I would expect var
to contain the value hello
, but alas, executing the above results in the following:
test.sh: command substitution: line 4: syntax error near unexpected token `('
test.sh: command substitution: line 4: `bash <(cat ./local/file.sh)'
var=
How can I accomplish my goal without using temporary files?
Best Answer
Those are the errors you get when trying to perform a process substitution in
bash
when the shell is running in POSIX mode. Thebash
shell does not support process substitutions in POSIX mode.bash
will run in POSIX mode when eitherset -o posix
has been used, orsh
.My hunch is that you have a script,
test.sh
, that you are running withsh test.sh
or that has a#!/bin/sh
hashbang line, and that yoursh
happens to bebash
. Another possibility is that the script does not have#!
-line at all, and it is being invoked bybash
-as-sh
in some other way.Instead, see to that your
test.sh
script is being invoked bybash
.Example:
If you want to do this in a portable way in your
test.sh
script using POSIXsh
:This would have the effect of the
bash
process reading the output ofcat
on its standard input, which is not quite the same as your process substitution variant (which leaves standard input alone). This matters if the script that the internalbash
shell executes does any form of reading of data from its standard input.If you need to leave the
bash
shell's standard input alone (because you need to read from it), you may possibly assume thatmktemp
is available and useWhere
cat script.sh
is understood to later be replaced by yourcurl
command.If you're comfortable with juggling file descriptors, you could also make file descriptor 3 a copy of the standard input descriptor before calling the
bash
shell, and then let the fetched script read from that:The
script.sh
script would then useread -u 3
to read from the original standard input stream, orutility <&3
to redirect that input stream into another utility.