Why is [[ ]] different then [ ]?


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Why is [[ ]] different then [ ]?
# 1  
Old 01-27-2009
Why is [[ ]] different then [ ]?

Please tell me why this outcome is different in a if statement. Some times I can use [ ] and its fine other times I need to use [[ ]].

Script:
#!/usr/bin/sh
CHECK1=`ps -ef | grep -v grep | grep lkdflkdfhdlkf | awk '{print $2}'`
if [ -n ${CHECK1} ]
then
echo "found"
else
echo "not found"
fi

Output:
./test.sh
./test.sh[3]: test: 0403-004 Specify a parameter with this command.
not found


Script:
#!/usr/bin/sh
CHECK1=`ps -ef | grep -v grep | grep lkdflkdfhdlkf | awk '{print $2}'`
if [[ -n ${CHECK1} ]]
then
echo "found"
else
echo "not found"
fi

Output:
./test.sh
not found
# 2  
Old 01-27-2009
[[ is keyword, [ is a shell builtin
This is from the 'Advanced Bash Scripting Guide':
Code:
The [[ ]] construct is the more versatile Bash version of [ ]. This is the extended test command, adopted from ksh88.

* * *

No filename expansion or word splitting takes place between [[ and ]], but there is parameter expansion and command substitution. file=/etc/passwd

if [[ -e $file ]]
then
  echo "Password file exists."
fi
 


Using the [[ ... ]] test construct, rather than [ ... ] can prevent many logic errors in scripts. For example, the &&, ||, <, and > operators work within a [[ ]] test, despite giving an error within a [ ] construct.


Arithmetic evaluation of octal / hexadecimal constants takes place automatically within a [[ ... ]] construct. # [[ Octal and hexadecimal evaluation ]]
# Thank you, Moritz Gronbach, for pointing this out.


decimal=15
octal=017   # = 15 (decimal)
hex=0x0f    # = 15 (decimal)

if [ "$decimal" -eq "$octal" ]
then
  echo "$decimal equals $octal"
else
  echo "$decimal is not equal to $octal"       # 15 is not equal to 017
fi      # Doesn't evaluate within [ single brackets ]!


if [[ "$decimal" -eq "$octal" ]]
then
  echo "$decimal equals $octal"                # 15 equals 017
else
  echo "$decimal is not equal to $octal"
fi      # Evaluates within [[ double brackets ]]!

if [[ "$decimal" -eq "$hex" ]]
then
  echo "$decimal equals $hex"                  # 15 equals 0x0f
else
  echo "$decimal is not equal to $hex"
fi      # [[ $hexadecimal ]] also evaluates!
 


 


 Following an if, neither the test command nor the test brackets ( [ ] or [[ ]] ) are strictly necessary. dir=/home/bozo

if cd "$dir" 2>/dev/null; then   # "2>/dev/null" hides error message.
  echo "Now in $dir."
else
  echo "Can't change to $dir."
fi
 
The "if COMMAND" construct returns the exit status of COMMAND.

Similarly, a condition within test brackets may stand alone without an if, when used in combination with a list construct. var1=20
var2=22
[ "$var1" -ne "$var2" ] && echo "$var1 is not equal to $var2"

home=/home/bozo
[ -d "$home" ] || echo "$home directory does not exist."

# 3  
Old 01-27-2009
[[ ]] is the "extended test facility"

word splitting and file name generation are not done inside the extended test facility, and therefore there is less need to quote.

You did not quote ${CHECK} in your first example and I think that is the difference. I don't know exactly what happens in the shell, but I think that the shell basically tried to use the '-n' test w/o an operand, possibly, because w/o quotes it treated the contents of ${CHECK} as a file name and could not find it (since it was null) which might be why the "not found" came up.

I quoted it using the test facility [ ] (not extended) which prevented file name expansion and allowed the result of ${CHECK} to be tested against the '-n' operator, and it worked fine, but w/o quotes I reproduced your errror.

I'm more familiar with ksh and HP-UX's "posix shell" (based on ksh) and the [[ ]] facility use is encouraged over [ ].

Last edited by rwuerth; 01-27-2009 at 06:28 PM.. Reason: changed abosulte wording to reflect that I'm unsure on some points. This way someone might verify or correct me.
# 4  
Old 01-27-2009
Quoting the "${CHECK1}" construct would create a zero length string if the variable was null, yes, that is correct. So [ ] would work for that.

I use ksh with [[ ]] -- simply to avoid problems like this. And any time I work with string variables I try to enclose them in double quotes so they are "seen" correctly by the shell.
# 5  
Old 01-28-2009
Great information everyone! Thanks for the education.
Login or Register to Ask a Question

Previous Thread | Next Thread
Login or Register to Ask a Question