How to tell if a string is not defined in a Bash shell script
but what if I want to check whether the variable has been defined at all? Or is there no distinction in Bash scripting?
@Ayos because if you don’t have quotes, the content of the variable is string-split and globbed; if it’s an empty string, it becomes [ -z ] instead of [ -z «» ] ; if it has spaces, it becomes [ -z «my» «test» ] instead of [ -z my test ] ; and if it’s [ -z * ] , then the * is replaced with the names of files in your directory.
12 Answers 12
I think the answer you are after is implied (if not stated) by Vinko’s answer, though it is not spelled out simply. To distinguish whether VAR is set but empty or not set, you can use:
if [ -z "$" ]; then echo "VAR is not set at all"; fi if [ -z "$VAR" ] && [ "$" = "xxx" ]; then echo "VAR is set but empty"; fi
You probably can combine the two tests on the second line into one with:
if [ -z "$VAR" -a "$" = "xxx" ]; then echo "VAR is set but empty"; fi
However, if you read the documentation for Autoconf, you’ll find that they do not recommend combining terms with ‘ -a ‘ and do recommend using separate simple tests combined with && . I’ve not encountered a system where there is a problem; that doesn’t mean they didn’t used to exist (but they are probably extremely rare these days, even if they weren’t as rare in the distant past).
You can find the details of these, and other related shell parameter expansions, the test or [ command and conditional expressions in the Bash manual.
I was recently asked by email about this answer with the question:
You use two tests, and I understand the second one well, but not the first one. More precisely I don’t understand the need for variable expansion
if [ -z "$" ]; then echo "VAR is not set at all"; fi
Wouldn’t this accomplish the same?
if [ -z "$" ]; then echo "VAR is not set at all"; fi
Fair question — the answer is ‘No, your simpler alternative does not do the same thing’.
Suppose I write this before your test:
Your test will say «VAR is not set at all», but mine will say (by implication because it echoes nothing) «VAR is set but its value might be empty». Try this script:
( unset VAR if [ -z "$" ]; then echo "JL:1 VAR is not set at all"; fi if [ -z "$" ]; then echo "MP:1 VAR is not set at all"; fi VAR= if [ -z "$" ]; then echo "JL:2 VAR is not set at all"; fi if [ -z "$" ]; then echo "MP:2 VAR is not set at all"; fi )
JL:1 VAR is not set at all MP:1 VAR is not set at all MP:2 VAR is not set at all
In the second pair of tests, the variable is set, but it is set to the empty value. This is the distinction that the $ and $ notations make. Ditto for $ and $ , and $ and $ , and so on.
As Gili points out in his answer, if you run bash with the set -o nounset option, then the basic answer above fails with unbound variable . It is easily remedied:
if [ -z "$" ]; then echo "VAR is not set at all"; fi if [ -z "$" ] && [ "$" = "xxx" ]; then echo "VAR is set but empty"; fi
Or you could cancel the set -o nounset option with set +u ( set -u being equivalent to set -o nounset ).
Using if elif fi in shell scripts [duplicate]
Quite a few commentators have suggested you use [[ rather than [ but that makes your script bash-specific. You’ll have fewer maintenance and portability issues if you can stick to plain old Bourne shell (sh) syntax.
6 Answers 6
Josh Lee’s answer works, but you can use the «&&» operator for better readability like this:
echo "You have provided the following arguments $arg1 $arg2 $arg3" if [ "$arg1" = "$arg2" ] && [ "$arg1" != "$arg3" ] then echo "Two of the provided args are equal." exit 3 elif [ $arg1 = $arg2 ] && [ $arg1 = $arg3 ] then echo "All of the specified args are equal" exit 0 else echo "All of the specified args are different" exit 4 fi
sh is interpreting the && as a shell operator. Change it to -a , that’s [ ’s conjunction operator:
Also, you should always quote the variables, because [ gets confused when you leave off arguments.
To note, this is a solution because the [[ construct is built into the shell while [ is another name for the test command and hence is subject to its syntax — see man test
I have a sample from your code. Try this:
echo "*Select Option:*" echo "1 - script1" echo "2 - script2" echo "3 - script3 " read option echo "You have selected" $option"." if [ $option="1" ] then echo "1" elif [ $option="2" ] then echo "2" exit 0 elif [ $option="3" ] then echo "3" exit 0 else echo "Please try again from given options only." fi
Gawd this looks quirky to me. Why no then after else ? It may actually not be quirky, but that’s how it looks, compared to C.
# cat checking.sh #!/bin/bash echo "You have provided the following arguments $arg1 $arg2 $arg3" if [ "$arg1" = "$arg2" ] && [ "$arg1" != "$arg3" ] then echo "Two of the provided args are equal." exit 3 elif [ $arg1 == $arg2 ] && [ $arg1 = $arg3 ] then echo "All of the specified args are equal" exit 0 else echo "All of the specified args are different" exit 4 fi # ./checking.sh You have provided the following arguments All of the specified args are equal
You can add set -x in script to troubleshoot the errors.