2

I am trying to run the test command from a string. The string contains the expression.

 TEST="! -e ~/bin/xyz"
 if [ `echo "$TEST"` ]; then
    echo running "$TEST";
 fi

However, the above if condition does evaluate to true but if I plug in the command directly (as below), it evaluates to false.

 if [ ! -e ~/bin/xyz ]; then
    echo running;
 fi

The second snippet's behavior is correct. Why is there is a difference and also how I can correct the first snippet to give me the right result?

  • 2
    I would not recommend storing test expressions in strings, as there isn't really a safe way to handle this. I'd recommend backing up and asking if there's a better way to do it. What's the actual problem you're trying to solve by storing test expressions in a string? – Gordon Davisson Nov 4 '18 at 7:29
3

The problem with first example is that you are testing whether the string that echo returns has non-zero length. One solution to this problem is to evaluate tested expression:

TEST="! -e ~/bin/xyz"
if eval "[ $TEST ]"; then
   echo running "$TEST";
fi

Notice, that brackets are inside eval, because [ is a command, so we evaluate this command together with variable $TEST as its argument.

  • 1
    Warning: as always, eval is an open invitation to weird bugs. It blurs the distinction between data and executable code (even more than it usually is in the shell), so you risk having something you thought was just data (e.g. a filename) get parsed & maybe executed as code. Basically, eval is only safe if you have full control over the string being evaluated (and if you have full control over it, you really shouldn't need eval). – Gordon Davisson Nov 4 '18 at 7:27
  • 1
    @GordonDavisson, and as usual at least we (most people) know eval is potentially dangerous as it does evaluate code, while most people don't know that the [ of several shells can also run commands. The OP's [ `echo "$TEST"` ] would also be an arbitrary command execution vulnerability if the content of $TEST was under the control of an attacker in ksh for instance (and at least a DoS in most shells because of the unquoted command substitution) – Stéphane Chazelas Nov 4 '18 at 11:21
  • 1
    you are testing whether the string that echo returns has non-zero length is incorrect. Because `...` is unquoted, it will be subject to split+glob and at least with the default value of $IFS containing SPC, $TEST will be split into 3 arguments, so it won't be a test for non-empty string. Here it doesn't work because ~ expansion is not performed upon parameter expansion. – Stéphane Chazelas Nov 4 '18 at 11:24

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.