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?

Yasser Zamani
  • 2,677
  • 2
  • 16
  • 16
  • 1
    Possible duplicate of [How to get both PIPESTATUS and output in bash script](https://superuser.com/questions/425774/how-to-get-both-pipestatus-and-output-in-bash-script) – jww Aug 04 '17 at 10:23
  • @jww, do them work via `sh -c ""`? – Yasser Zamani Aug 04 '17 at 11:04

3 Answers3

12

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.

u1686_grawity
  • 426,297
  • 64
  • 894
  • 966
  • 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 '15 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
rzr
  • 314
  • 3
  • 8
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

atmchem
  • 11
  • 2
  • That's expected behaviour: single quotes do not cause variable interpolation. See https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash – silviot May 13 '19 at 13:58