sh and/or operation 

sh$ true && echo aaa
aaa
sh$ true || echo aaa
sh$ false && echo aaa
sh$ false || echo aaa
aaa

test on command result 

$ if true; then echo yes; else echo no; fi
yes
$ if false; then echo yes; else echo no; fi
no
$ if echo something | grep .; then echo found; else echo no; fi
something
found

cmd:test 

String compare 
equal:         STRING1 = STRING2
not equal:     STRING1 != STRING2
fret=$?                 # get func ret code
if [ $fret != 0 ] ; then
  # wget returned error
  $echo "Download error.\nNo log written."
else
Numeric compare 
[ "0$show" -ge "2" ] && set -xv
[ "0$show" -eq "1" ] && set -x
INTEGER1 -eq INTEGER2
       INTEGER1 is equal to INTEGER2
-ge  -gt -le -lt -ne
Flag tests 
[-n] STRING
       the length of STRING is nonzero
-z STRING
       the length of STRING is zero
[ -n "$Trig1" -a -n "$Trig1" ] && { action if both trigger is set. }
[ -z "$Trig1" -a -z "$Trig1" ] || { action if either trigger is set }
[ "$Trig1" -o "$Trig1" ] || {
[ -z "$Trig1" -a -z "$Trig1" ] && {
  action if neither trigger is set.
  ie, if either trigger is set, there will be no such action.
}
Connectives 
`! EXPR'

True if EXPR is false.

`EXPR1 -a EXPR2'

True if both EXPR1 and EXPR2 are true.

`EXPR1 -o EXPR2'

True if either EXPR1 or EXPR2 is true.

$ [ "T" -a "" ] && echo yes
$ [ "T" -a "T" ] && echo yes
yes
$ [ "" -a "T" ] && echo yes

tcsh test 

space for if 
host:~/bin>if ( -f dofor  ) echo aaa
aaa
host:~/bin>if ( "a"=="a" ) echo aaa
if: Expression Syntax.
host:~/bin>if ( "a" == "a" ) echo aaa
aaa

test for files 

Usage 

$ touch aa
$ dir aa
-rw-------   1 suntong  glan            0 Dec  7 13:19 aa
$ [ -f aa ] && echo aa
aa
$ [ -s aa ] && echo aa
$

Help 

-e FILE
       FILE exists
-f filename    True if filename  exists  and  is  a  regular
               file.
-s filename    True  if  filename  exists  and  has  a  size
               greater than zero.

test, $var or "$var" 

If you want to test a varible is empty or not, you can either say

[ $var ] or [ "$var" ]

But if you can't guarantee that $var is only one word, you'll get error "[: too many arguments"

documented on: 1999.12.21 Tue 09:20:03

testing empty 

Synopsis 

b=''
b=T
[ "$b" ] && echo b is not empty!       # way to test empty!
[ "$b" ] || echo b is empty!           # way to test not empty!
if [ "$b" ] ; then echo b is true! ; else echo b is false; fi

Usage 

[ "$b" ] || echo b is empty!           # lazy way to test not empty!
[ -z "$b" ] && echo b is empty.        # formal way to test empty!
[ ! -z "$b" ] && echo b is not empty.  # formal way to test empty!

Trying History 

b=''
if [ "$b" ] ; then echo b is true! ; fi
if [ ! "$b" ] ; then echo b is false! ; fi

yield:

+ [  ]
+ [ ! ]
/home/users/suntong/bin/sh.test.script: test: argument expected

Right way:

[ "$b" ] && echo b is not empty!       # way to test empty!
[ "$b" ] || echo b is empty!           # way to test not empty!

test empty and something else 

Symptom 

this will not work:

printf "Writing to " >&2
  # for "txt" command with no 'saved_name' parameter provided,
  # write to stdout instead of saving to file
if [ "$1" ] || [ $sfunc = txt ] ; then
  printf "standard output" >&2
  save_to=
else
  save_to=T                   # will save
fi
+ printf Writing to
Writing to + [ aaaa ]
+ printf standard output

Conclusion / Solution 

use [ -z ] !

more on empty test: 

_empty_test(){

if [ "$1" ]; then
  echo "\$1=$1";
else
  echo "\$1 is empty";
fi

echo "== ${1-minus}, ${1+plus}\n"

}

empty_test(){
  val1=$1;
  val2=${1+"$@"};

  _empty_test $val2 ; _empty_test "$val2" ;     # different!
}

calls: call empty_test with ''

Tip !!
+ empty_test
val1=
val2=
+ _empty_test
+ [  ]
+ echo $1 is empty
$1 is empty
+ echo == minus, \n

minus, 

+ _empty_test
+ [  ]
+ echo $1 is empty
$1 is empty
+ echo == , plus\n

Conclusion 

[ ] will always tells you that string is empty

but ${+} and ${-} can tell the difference!

more on parameter passing 

empty_test 'a' 'b'
+ empty_test a b
val1=a
val2=a b
+ _empty_test a b
+ [ a ]
+ echo $1=a
$1=a
+ echo == a, plus\n

a, plus 

+ _empty_test a b
+ [ a b ]
+ echo $1=a b
$1=a b
+ echo == a b, plus\n
Tip !!

so we can see passing $val2 or "$val2" is different

documented on: 1999.12.06 Mon 12:02:39

bash space for test 

space for test 
:~/bin$ if [ "a" = "a" ] ; then echo aaa ; fi
aaa
:~/bin$ if [ "a"="a" ] ; then echo aaa ; fi
aaa
:~/bin$ if ["a"="a"] ; then echo aaa ; fi
bash: [a=a]: command not found
or operator 
if [ "$2" = "" -o "$2" = "@" ]
then
  saved_name=`basename $url`
else
  saved_name=$2
fi

documented on: Sun 04-04-99

> According to several man pages I got, the commands are -h, -l and -L.
> What should I choose when doing the shell script programming?

Welcome to the wonderful world of Unix, where people never seem te be able to agree on such simple things. The answer is, unfortunately, "It depends what Unix you are on".

> Correct me if I'm wrong:
> I think the gnu flavor is -L, that is bash's buildin test and test from
> gnu (.../gnu/test) use -L. (and ksh)

Correct.

> sh also has buildin test? because:

Yes.

> and sh buildin test for symbolic link files is -h and (?) -L.
> Is above correct?

See the local man sh, where the builtin 'test' is documented.

> But why when it comes to real testing, I got weird results?
> sh
> $ ls -l index.htm
> lrwxrwxrwx   1 tongsun  glan           31 Nov  5 11:11 index.htm ->
> ../../...
> $ [ -h index.htm ] && echo aa
> aa
> $ [ ! -h  index.htm ] && echo aa
> $
> hmm..., seems good, but how about:
> sh
> $ [ -L index.htm ] && echo aa
> test: argument expected
> why?

The -L is not a recognized flag for the built-in '[' command.

> besides,
 > $ test " -l index.htm" && echo no
 > no
 > $ test "! -l index.htm" && echo no
 > no
 > $ test "-h  index.htm" && echo aa
 > aa
 > $ test "! -h  index.htm" && echo aa
 > aa
...
 > what's going here, why test is always true?

Because you pass all these tests A SINGLE argument. If you write "-h index.htm" (in double quotes) then that is a single argument which is evaluated a test "is this string not empty". Since this is true in ALL the above cases, you get the above results.

try:

$ test -l index.htm && echo no

And it will work much better.

Ruurd.

   ``test -h'' works on FreeBSD 4.0, HP-UX 11.10, and DEC UNIX
5.0.
ksh on DEC UNIX 5.0:
$ type test
test is a shell builtin
$ touch File1
$ ln -s File1 File2
$ test -h File1 && echo "File1 is a symlink."
$ test -h File2 && echo "File2 is a symlink."
File2 is a symlink.
$ /bin/test -h File1 && echo "File1 is a symlink."
$ /bin/test -h File2 && echo "File2 is a symlink."
File2 is a symlink.
$

The behavior is the same for HP-UX and FreeBSD.

> and sh buildin test for symbolic link files is -h and (?) -L.
> Is above correct?
Yes.
> $ test " -l index.htm" && echo no
> no

And I've got no evidence an "-l" flag exists. Plus arguments aren't going to be separated if you put quotes around them! All the following tests will pass!

Example:
$ test "abc" && echo Passed.
Passed.
$ test "abcdeffg hijklmnop" && echo Passed.
Passed.

Chris Costello

documented on: 1999.11.09 Tue 10:45:41

Usage 

The -L or -H option to test.

if [ -h <file> ]; then
        echo "It is a symbolic link"
fi
if [[ -L ${FILE} ]]; then
    : symlink
else
    : not a symlink
fi

Help 

from gnu test 

-L file True if file exists and is a symbolic link.

no -h option

but -L can't be used in sh scripts! :

$ [ -L tree ] && echo aaa
test: argument expected

documented on: 11:38:03

boolean controling var 

Usage 

iitrc:~/temp$ unset sc; [ "$sc" == "1" ] && echo aaa
iitrc:~/temp$ sc=0; [ "$sc" == "1" ] && echo aaa
iitrc:~/temp$ sc=1; [ "$sc" == "1" ] && echo aaa
aaa

Trying History 

iitrc:~/temp$ [ $sc ] && echo aaa
iitrc:~/temp$ sc=1
iitrc:~/temp$ [ $sc ] && echo aaa
aaa
iitrc:~/temp$ sc=0
iitrc:~/temp$ [ $sc ] && echo aaa
aaa

— sc not defined, no show

— sc defined, no matter 0 or 1, show

iitrc:~/temp$ [ \!\$sc ] && echo aaa
aaa
iitrc:~/temp$ sc=1
iitrc:~/temp$ [ \!\$sc ] && echo aaa
aaa

— the same as to !$sc

iitrc:~/temp$ [ $sc == 1 ] && echo aaa
aaa
iitrc:~/temp$ sc=0
iitrc:~/temp$ [ $sc == 1 ] && echo aaa
iitrc:~/temp$

— yeah, this is the right way

iitrc:~/temp$ unset sc
iitrc:~/temp$ [ $sc == '1' ] && echo aaa
[: ==: unary operator expected

— new problem

iitrc:~/temp$ [ $sc ] && [ $sc == '1' ] && echo aaa
iitrc:~/temp$ sc=1; [ $sc ] && [ $sc == '1' ] && echo aaa
aaa
iitrc:~/temp$ sc=0; [ $sc ] && [ $sc == '1' ] && echo aaa
iitrc:~/temp$

— Got it!

documented on: 05-04-99 20:35:04

sh: boolean value? 

> How can I assign boolean value to a varible and test it later:
>
> if [ $b ] ; then echo b is true! ; fi
> if [ !$b ] ; then echo b is false! ; fi
> the above code will say that b is both true & false no matter what
> value I give to b: 0,1, true & false.

man test — the contents of b are not parsed, it just checks whether it's set to something or not:

$ b=
$ if [ "$b" ] ; then echo empty string = true
> else echo empty string = false; fi
empty string = false
$ b=something
$ if [ "$b" ] ; then echo non-empty string = true
> else echo non-empty string = false; fi
non-empty string = true

/* era */

sh: boolean value? 

Old-timers use `case': it's always been a shell builtin.

b=0
...
case $b in
0)
    echo b is still zero
    ;;
*)
    echo b is no longer zero
    ;;
esac

Tim.

documented on: 1999.09.22 Wed 15:19:48

Checking file exists with wildcard? 

> # Is there a nice way to check if any of a group of files
> # exists using a wildcard? I don't want to get the pesky
> # "No match" messages from ls or test when nothing exists.
for file in $mask;do break;done
if [[ -a $file ]]
   then
   echo "files exist matching $mask"
else
   echo "no files exist matching $mask"
fi

No processes.

Empty dir 

> check if there is any file exist in /home/my_directory
if [ -z "`ls`" ]
        then
        echo "no files found."
else
        echo "files found."
fi

documented on: 04-20-99 15:37:59