I am no shell scripting expert, but I have written a lot of bash code in my day. Most of my shell scripting know-how has come from trial-and-error and desperate googling. This has (slowly) taught me a few nifty tricks and some of the more interesting details of how bash actually “works” (for lack of a better word). I’d like to share one small tidbit with you now.
The “[" program.
No, that's not a mistake. There actually is a program on UNIX systems called "[", and it generally lives in /usr/bin. Don't believe me? Check out this which command:
# which [
/usr/bin/[
Isn't that odd? On some systems (namely Fedora-variants) the "[" program is actually a symbolic link ("symlink" among friends) to a program called "test":
# ls -l /usr/bin/[
lrwxrwxrwx root /usr/bin/[ -> test
You see, every good UNIX-like OS ships with a handy utility called test (man 1 test). It's a simple program that can answer questions like "is variable $foo greater than 42?", like this:
# foo=43
# test $foo -gt 42
# echo $?
0
# test $foo -lt 42
# echo $?
1
It can do a whole slew of other comparisons too, including math, string comparisons, file operations (does file $foo exist?), and a bunch of other stuff (man 1 test for full details)
The "test" program gives output solely by its exit status (that's what $? stores after you run a program in bash). That way, you can use it in bash if statements, like this:
foo=43
if test $foo -gt 42; then
echo $foo is greater than 42
else
echo $foo is NOT greater than 42
fi
It turns out that our good UNIX forebears hated typing, so they invented the "[" program, which does exactly the same thing, but it looks a heck of a lot like a C conditional when used in shell scripts, like this:
foo=43
if [ $foo -gt 42 ]; then
echo $foo is greater than 42
else
echo $foo is NOT greater than 42
fi
The only difference between "test" and "[" is that "[" requires you to have a matching "]" as its last argument or it complains on stderr. Isn't that nifty? I think so. This explains why, by the way, you have to have spaces before and after the "[" and "]". It's because "[" is actually a program name and "]" is just a command line argument like any other argument.
Now get back to that shell script you were hacking.