# this is a comment.
In shell programming, you don't need to declare variables before using them.
Set the value of a variable
You can't have spaces on either side of the equals sign.
my_var = "Wodehouse";
Get the value of a variable
Precede the variable with a '$' to get the value of it. For example:
echo $my_var; # prints out "Wodehouse"
Variable substitution
Same as Perl, if you use double quotes, variable substitution will take place, and if you don't, it won't.
For example, if my_var contains "Wodehouse":
echo "$my_var"; # prints out "Wodehouse"
echo '$my_var'; # prints out "$my_var"
This will read user input and put it in "my_var":
read my_var;
When a shell script starts, some variables are initialized from values in the environment.
Some common environment variables
$HOME
The home directory of the current user.
$PATH
A colon-separated list of directories to search for commands.
$PS1
A command prompt, frequently $, but in bash you can use some more complex values.
$PS2
A secondary prompt, used when prompting for additional input; usually >.
$IFS
An input field separator. This is a list of characters that are used to separate words when the shell is reading input, usually space, tab, and newline characters.
$0
The name of the shell script.
$#
The number of parameters passed.
$$
The process ID of the shell script, often used inside a script for generating unique temporary filenames; for example /tmp/tmpfile_$$.
If you script is invoked with parameters, some additional variables are created:
$1, $2, ...
The parameters given to the script.
$*
A list of all parameters, in a single variable, separated by the first character in the environment variable $IFS. If $IFS is modified, then the way $* separates the command line into parameters will change.
$@
Same as $* except it doesn't use the $IFS variable.
Note: There has to be a space after the opening bracket and before the closing bracket; otherwise you will get an error.
if [ this_is_true ]
then
echo "yes, that's true.";
elif [ this_other_thing_is_true ]
then
echo "yes, that other thing is true."
else
echo "no, neither of those are true.";
fi
Use '-f'.
You can use '-e' if you want, but historically the -e option has not been portable, so -f is usually used.
if [ -f $1 ]
then
echo "yes, that file exists.";
fi
Use '-d'.
if [ -d $1 ]
then
echo "yes, that's a directory.";
fi
Use -r for readable
Use -w for writable
Use -x for executable
#!/bin/bash
if [ -r some_file ]
then
echo "yes, that file is readable.";
fi
Use -s. If returns true if the file has nonzero size.
#!/bin/bash
if [ -s some_file ]
then
echo "yes, that file has a non-zero size. You probably don't want to overwrite it.";
fi
String comparison is a little different in the shell.
string1 = string2
True if the strings are equal.
string1 != string2
True if strings are not equal.
-n string
True if string is not null (i.e. not an empty string).
-z string
True if string is null (i.e. an empty string).
A subtle problem with string comparison
Suppose you have this statement:
if [ $string1 = $string2 ]
then
echo $something;
fi
Now suppose
$string1 = "" and
$string2 = "boat".
The above code doesn't evaluate to this:
if [ "" = "boat"]
instead it evaluates to this:
if [ = "boat" ]
Which will produce an error. To avoid this tragedy, write if statements like this:
if [ "$string1" = "$string2" ]
echo "hello there";
echo $HOME;
# one way to do it
for s in "a" "b" "c" "d"
do
echo $s
done
# using wildcards and $(command) syntax
for file in $(ls *.pl)
do
cat $file
done
# another way to do it
for ((i = 0 ; i <= 5; i++))
do
echo "Repetition number $i"
done
while [ condition ]
do
echo "something"
done
Notice the single bracket and the two semicolons at the end. Those aren't mistakes.
read $input;
case "$input" in
yes | y | Yes | YES) echo "YESSSS!";;
no ) echo "NOOO :(";;
* ) echo "default answer.";;
esac
function_name() {
statements
}
You must always define a function before you can invoke it.
When a function is invoked, the $*, $@, $#, $1, $2 etc variables are replaced by the parameters to the function. That's how you read the parameters passed to the function. When the function finishes, they are restored to their previous values.
Local variables
You can declare local variables in functions like this:
function_name()
{
local lo_var = "some var";
}
Returning values
function_name()
{
return 1;
}
Calling a function
Suppose we have a function foo. Here's how we would call it (notice the lack of parens):
# one way to call
foo
#passing a parameter
foo "$1"
You can break out of loops by using break;
You can skip the current iteration of a loop by using continue;
Script 1 (no eval):
foo=10;
x="foo";
y='$'$x;
echo $y;
This prints out "$foo".
Script 2 (with eval):
foo=10;
x="foo";
eval y='$'$x;
echo $y;
This prints out "10".
Use the exit command:
exit n;
n is the exit code. The choices for the exit code are:
0 if the program exited normally
1-125 if there was an error.
By default, variables created in a shell are not available in further subshells invoked from that shell. The export command makes variables available in subshells. For example:
export board_game="Settlers of Catan";
Use the shift command. The shift command moves all parameter variables down by one, so that $2 becomes $1 etc. The previous value of $1 is discarded. $0 remains unchanged.
If your script contains 10 or more parameters, you'll need shift to access them.
Notice how we put "$1" in quotes. Read the "a subtle problem" section in 'String Comparison' if you don't understand why.
while [ "$1" != "" ]
do
echo "$1";
shift;
done
Use the trap command. The syntax is:
trap [run these commands] [for this signal].
Remember that scripts are normally interpreted from top to bottom, so you must specify the trap command before the part of the script you wish to protect.
For example, here's a trap that prints "exiting" when someone hits Ctrl-C:
trap "echo 'exiting'" SIGINT
Runs the command inside the parens and shows the output. For example, this will print out all the users currently logged in:
echo "The current users are $(who)";
This is a little complex in shell programming. You have to use the $(()) operator:
x=$(($x+1));
Suppose you want to cat out files 1_tmp through 10_tmp. Here's how you would do it:
for i in 1 2 3 4 5 6 7 8 9 10
do
cat ${i}_tmp
done
You can also use the ${} syntax for other things:
${param:-default}
If param is null, set it to the value of default.
${#param}
Gives the length of param.
${param%word}
From the end, removes the smallest part of param that matches word and returns the rest.
${param%%word}
From the end, removes the largest part of param that matches word and returns the rest.
${param#word}
From the beginning, removes the smallest part of param that matches word and returns the rest.
${param##word}
From the beginning, removes the largest part of param that matches word and returns the rest.