Páginas

Sunday, October 3, 2010

Bash 101: Variables and Conditions

First off I would like to make a little note on the use of quotes. In the shell, variables are separated by whitespaces, if you want those characters to belong to the variable you'll have to quote them.

There are 3 types of quotes, double, single and the backslash, that have the following results:
  • Double - Accepts whitespaces and expands other variables
  • Single -   Accepts whitespaces and doesn't expand other variables
  • Backslash - Escapes the value of $
In my previous post I've talked about normal variables, here I'll talk about the other two types of variables, environment and parameter.

Environment Variables


At the start of any shell script some variables are initialized with values defined in the environment (you can change them with export or in the .bash_profile file). For convenience these variables are all uppercase, as opposed to the user defined that should be lowercase. Here's a list of the main ones and a brief description.
  • $HOME - Home directory of the current user
  • $PATH - The list of directories to search commands
  • $PS1 - The definition of the command prompt (eg: \h:\W \u\$)
  • $PS2 - The secondary prompt, usually >
  • $IFS - Input Field Separator. List of characters used to separate words when reading input
  • $0 - The name of the shell script
  • $# - The number of parameters passed
  • $$ - The PID of the shell script (normally used to create temporary files)
If you want to check all your environment variables just type printenv in the shell.

IBM has a pretty good hands on post to understand the setting and unsetting of environment variables, here, and refer to this other post for a more extensive overview of variables.

Parameter Variables


If your scripts is invoked with parameters it has some more variables which are defined (you can check if there are any parameters if the $# variable has a value greater than 0). These are the parameter variables:
  • $1, $2, ... - The parameters given to the script in order
  • $* - A list of all parameters in a single variables, separated by the first character in IFS
  • $@ - A variation of $*, that always uses a space to separate the parameters
I've written a small script that should make the difference between $* and $@ clear:

#!/bin/bash

export IFS=*
echo "IFS = $IFS"
echo "With IFS - $*"
echo "Without IFS - $@"

exit 0

Run it as ./script param1 param2 param3 ...

Note: The export command sets the variable for the script and all its subordinates.

Conditions


One the fundamental things of any programming language is the ability to test conditions. A shell script can test the exit code of any command it invokes, even of scripts written by you. That is why it is very important to include an exit command with a value (0 if it is ok), at the end of all your scripts.

The commands used to test conditions are two synonyms, test and [. Obviously, if you use [ it must have a matching ], and because it makes your code much easier to read, this is the most used construct.

In a shell script, a test should look something like

if [ -f file ]
then
    echo "File exists"
else
    echo "File does not exist"
fi

The exit code of either these commands is what determines the veracity or not of the statement (again, 0 for true and 1 for false). A little thing to remember is that [ is a command, therefore you must put spaces between it and the condition, or else it won't work.

There are 3 types of conditions that can be used with these commands:

String Comparison

  • string1 = string2 - True if strings are equal
  • string1 != string2 - True if strings are not equal
  • -n string - True if string is not null
  • -z string - True if string is null (empty)

Arithmetic Comparison

  • exp1 -eq exp2 - True if the expressions are equal
  • exp1 -ne exp2 - True if the expressions are not equal
  • exp1 -gt exp2 - True if exp1 is greater than exp2
  • exp1 -ge exp2 - True if exp1 is greater than or equal to exp2
  • exp1 -lt exp2 - True if exp1 is less than exp2
  • exp1 -le exp2 - True if exp1 is less than or equal to exp2
  • ! exp - True if the expression is false and vice versa

File Conditional

  • -d file - True if the file is a directory
  • -e file - True if the file exists (-f is usually used instead)
  • -f file - True if the file is a regular file
  • -g file - True if set-group-id is set on file
  • -u file - True if the set-user-id is set on file
  • -s file - True if the file has nonzero size
  • -r file - True if the file is readable
  • -w file - True if the file is writable
  • -x file - True is the file is executable
These are the more commonly used options, for a complete list type help test in your bash.

No comments: