3

I would like to write a small part of a script that saves the error status, executes some other code, and sets the error status to the original error status. In Bash it looks like this:

<< some command >>; _EXIT=$?;( <<other code here>> ;exit $_EXIT)

But I need code that will run no matter if it is being run under bash, zsh, csh or tcsh. I do not know which shell will be used in advance, because it is decided by the user. The user also decides << some command >>.

It is safe to assume that << other code >> will work in all shells, but it is not safe to assume that you can write a file (so putting it into a file will not work).

Background

GNU Parallel executes commands given by the user in the shell decided by the user. When the command is finished, GNU Parallel has some cleanup to do. At the same time GNU Parallel needs to remember the exit value of the command given by the user. The code run before the snippet above is the user given command. << other code >> is the cleanup code.

  • 1
    You forgot fish :-) ... The problem is that variable assignment is different for sh/csh/fish, and it's not easy to make this compatible (using test or any other commands will never work, since that will reset $?)... I'm not sure what you're trying to do here, why don't you just execute your script with /bin/sh or whatever? ... The only option is to create separate scrips. – Martin Tournoij Jan 15 '15 at 23:59
  • I'm not crystal clear on what the goal is. As a general construct, you might be better with _EXIT=$?; <<other code here>>; (exit $_EXIT), to allow the "other code" to modify the state of the shell (e.g., cd, set variables, etc.) – Scott Jan 16 '15 at 0:02
  • @Scott That will not work in csh. – Ole Tange Jan 16 '15 at 0:27
  • @Carpetsmoker Because the user of this code decides which shell I must use, and I do not know beforehand. – Ole Tange Jan 16 '15 at 0:28
  • 1
    You can't generally use the same code in both sh-like shells and csh-like shells. Their syntaxes for variable assignment and conditionals are totally incompatible. – Barmar Jan 16 '15 at 20:36
0

This answer works in bash-like shells and csh-like shells, and it doesn’t require perl:

sh -c '<< other code >>; [ "$0" != "" ] && exit "$0"; exit "$1"' "$?" "$status"

or you can add a dummy/pad parameter:

sh -c '<< other code >>; [ "$1" != "" ] && exit "$1"; exit "$2"' foo "$?" "$status"

and the test can be changed to [ ! -z "$0" ] (or "$1").  I don’t know whether it will work in zsh or fish.  Every shell that I’m familiar with will evaluate $? and $status when the command is parsed, and pass them to the sh -c command as parameters.  The sh shell assigns them to the last two positional parameters.  When the “other code” finishes, the shell will check the positional parameter that got its value from $? to see whether it is null or non-null, and exit with the appropriate positional parameter value.

This will fail if the ambient shell uses something other than $? or $status to hold the exit status.  It will also fail if the shell allows $? to be set (non-null) if it is not the exit status, or if $? is an invalid character sequence that causes the entire command to be rejected as a syntax error.

  • tcsh is happy. csh complains: Illegal variable name. – Ole Tange Jan 24 '15 at 0:05
  • You sure about those !bangs? In a classic csh the only means of escaping one is with a backslash - not even hard-quotes will do it. – mikeserv Jan 24 '15 at 0:19
0

Use perl:

perl -e '$a=shift; `<< other code >>`; exit $a' $? # Fails in csh

Edit This works in csh, too (and zsh, tcsh, sh, pdksh, ksh93 - though not fish):

perl -e '$a=shift; `<< other code >>`; $a=~s/h// and exit $a; exit shift' "$?h" "$status"
  • 3
    Well, if that's a valid answer, why not sh -c '_EXIT=$?; <<other code here>>; (exit $_EXIT)'? – Scott Jan 16 '15 at 0:32
  • @Scott Just tested your solution in tcsh. It does not work: It seems to always sets $? to 0. – Ole Tange Jan 16 '15 at 0:38
  • @Scott With a small change: sh -c '_EXIT='$?'; <<other code>>; (exit $_EXIT)' it works and would be a useful answer, too. – Ole Tange Jan 16 '15 at 1:04
  • This executes << other code >> under sh, not under the ambiant shell. This is not what your question requests, although I expect you'd only care for code that works identically anyway. – Gilles Jan 16 '15 at 1:45
  • 2
    And for that matter this is a syntax error in csh. The csh equivalent of $? is $status. – Gilles Jan 16 '15 at 1:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.