Does not work to execute command in double bracket

2019-03-03 08:55发布

In an attempt to stay consistent i have tried to use double brackets [[ ]] in all my if statements. I did however get into a problem when i was going to check the return value for a command i wanted to run. After testing several ways of creating an if statement i found that only without brackets could i execute a command.

The following does not work:

if [[ $command ]] ; then
    echo "something"
fi

if [[ $(command) ]] ; then
    echo "something"
fi

if [[ ${command} ]] ; then
    echo "something"
fi

and the code above makes the if loop true even when the command was not run. since the code above doesnt work with braces it doesnt work to use this either:

[[ $command ]] || echo "failed"

and it doesnt work in a subshell either.

The following works:

if $command ; then
    echo "something"
fi

if $(command) ; then
    echo "something"
fi

Why doesnt it work to place a command in an if loop with brackets, and why does the if loops above report true when it didnt even run the command ? I'm using bash version 4.1.9. Ive tried this many times and the if loops are just as simple as the ones i typed above, it just checks if a command was run successfully and exits if it wasnt.

标签: linux bash shell
3条回答
三岁会撩人
2楼-- · 2019-03-03 08:55

If you're just checking the return value of the command, drop the double brackets.

if $command
then
    echo "Command succeeded"
else
    echo "Command failed: $!"
fi

The double brackets are a test command. (Well, not really, but their a takeoff of the single square brackets that were an alias to the test command.) In early Bourne shell, you would see things like:

if test -z "$string"
then
    echo "This is an empty string"
fi

The square brackets were syntactic sugar:

if [ -z "$string" ]
then
    echo "This is an empty string"
fi

So, if you're not doing an actual test, you can eliminate the double or single square brackets.

If you're using square brackets, you should use the double ones and not the single ones because the double ones are a bit more forgiving and can do a bit more:

if [ -z $string ]    #  No quotes: This will actually fail if string is zero bytes!

if [[ -z $string ]]  #  This will work despite the lack of quotes
查看更多
家丑人穷心不美
3楼-- · 2019-03-03 09:02

The short answer is:

  • [ and [[ expect an expression.

  • if expects a command.

Saying:

[[ $(command) ]]

would essentially execute:

[[ -n <command_output> ]]

which may or may not be what you want. On the other hand, saying:

$command && echo something || echo other

would echo something or other based on the return code of the command (0 and non-zero respectively).

查看更多
Ridiculous、
4楼-- · 2019-03-03 09:20

Double braces are a shortcut for test. In your examples, what's happening is that you're testing the shell variable $command for existence.

if [[ $PWD ]]; then
    echo PWD is set to a value
fi

if [[ $NOT_A_REAL_VAR ]]; then
    echo Nope, its not set
fi

In your second example, you're using command substitution to check that command output something on standard output.

if [[ $(echo hi) ]]; then
    echo "echo said hi'
fi

if [[ $(true) ]]; then #true is a program that just quits with successful exit status
    echo "This shouldn't execute"
fi

Your third example is the same as your first, pretty much. You use the curly braces if you want to group your variables. for example if you want to put an 's' after something.

WORD=Bike
echo "$WORDS" #won't work because "WORDS" isn't a variable
echo "${WORD}S" # will output "BikeS"

Then in your fifth example, you are running the program that is sitting inside command.

So, if you want to test some strings, use [[ ]] or [ ]. If you just want to test the exit status of a program, then don't use those, just use a bare if.

Check man test for details on the braces.

查看更多
登录 后发表回答