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?

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
Ashwin
  • 76
  • 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 04 '18 at 07:29

1 Answers1

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.

Kusalananda
  • 333,661
jimmij
  • 47,140
  • 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 04 '18 at 07: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$TESTwas under the control of an attacker inksh` for instance (and at least a DoS in most shells because of the unquoted command substitution) – Stéphane Chazelas Nov 04 '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 04 '18 at 11:24