10

When I run

curl | tee test.txt; echo ${PIPESTATUS[0]}

I correctly see

curl: try 'curl --help' or 'curl --manual' for more information

2

But when I try to run exactly same command using '/bin/sh':

sh -c "curl | tee test.txt; echo \${PIPESTATUS[0]}"

I get

curl: try 'curl --help' or 'curl --manual' for more information

sh: 1: Bad substitution

How we can resolve Bad substitution problem, please?

2

4 Answers 4

13

You solve it by not using sh.

The PIPESTATUS variable specifically, and the ${var[idx]} array syntax in general, are features specific to the Bash shell. They do not exist in POSIX sh, and even shells that do have arrays might use a different syntax.

It just happens that some Linux distributions symlink their /bin/sh to Bash. Other distributions, however, symlink it to dash, Debian Almquist Shell. Both are compatible with POSIX sh scripts, but only Bash accepts the ${PIPESTATUS[…]} syntax.

So if you want to use it, run bash -c "…" instead.

1
  • 1
    Because its part of the question to use sh. Better answer bellow, with a hack. Not a better "solution", though (I'll agree that a better solution is to avoid sh)
    – DrBeco
    Jul 11, 2015 at 21:47
8

Workaound for '/bin/sh' or busybox

status=0
eval ` { ls /dontexists || echo status="$?"; } | tee /dev/null`
echo "# status=${status}"

Trace :

busybox sh ~/bin/test.sh 
+ status=0
+ ls /dontexists
+ tee /dev/null
ls: /dontexists: No such file or directory
+ echo status=1
+ eval status=1
+ status=1
+ echo # status=1
# status=1
1
  • This will fail if ls succeeds. Then this will eval all the file names. Feb 6 at 7:57
1

Also 'bash -c' seems to have a problem with it when called from tcsh:

bash -c "curl | tee test.txt; echo \${PIPESTATUS[0]}"

PIPESTATUS: Undefined variable.

This works for me from tcsh:

bash -c 'curl | tee test.txt; echo ${PIPESTATUS[0]}'

curl: try 'curl --help' or 'curl --manual' for more information
2

GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)
called from tcsh 6.17.06

1
0

You probably ask this question, because you use the busybox shell that does not have the PIPESTATUS array. In that case, the only option will be to set -o pipefail. But if you are using one of the almost extinct shells that does not have PIPESTATUS or -o pipefail, then you may consider writing temporary files either for the intermediate output or the return value.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .