Since /bin/sh is available on every Unix system, it is the shell of
choice for writing scripts, even while it has much less power than the other
shells. Therefore it is a good idea to learn the basic syntax. while man sh
will give you the full story, here are some of the most common constructs.
Probably you'd be more portable by just learning perl and using that
everywhere. The shell can be used interactively or as a script.
Flow control |
for |
if |
for var [in word-list]
do
cmds
done
|
if cmds
then
cmds
[elif
cmds
then
elif_cmds]
[else
else_cmds]
fi
|
case |
while |
case word in
pattern1) cmds;;
..
patternN) cmds;;
esac
|
while cmds
do
cmds
done
|
Tests |
What irks me most is the shitty syntax for conditions. Here my
personal back-breakers:
- conditions test expressions with the syntax [
expression ] (note the spaces inside the brackets!)
- logical operators: and is -a,
or is -o, not is !. All
have to be set apart by space! Or can also be emulated by
[ test1 ] || [ test2 ]
- if [ ! -e file ])
- operators for file tests: -r file (readable),
-d file (directory), -e file (exists)
- string comparisons:= (string equal), !=
(strings different). May not have space around them!
- numeric comparisons:-eq (numbers equal). Note the
string/number thing is the other way round than it is in Perl,
also note the - in -eq
- there must be a semicolon before the keyword that
indicates the start of the dependent block, if both are on the
same line: like if [ -e file -a -r file ]; then echo
"Yep"; fi or for x in ABC*.txt; do sort $x;
done
|
Your usual constructs, with fi etc
instead of blocks. Cmds means a list of commands. Bracketed parts
are optional. Keywords must start on a fresh line, or after a
semicolon. Patterns can use filename expansion (without the
exeptions), word is usally a variable. For without in uses the
position parms. You can use continue and break
with loops. |
|
Basics |
Commands |
Each command can be given arguments during its
invocation. It turns into a process, reads data from standard
input, outputs results to standard output, errors to standard
error. Upon finishing it returns an errorlevel into $?,
which is 0 if successful, positive otherwise. |
Filenames |
Any filename is possible, as long as the script
has the magical #!/bin/sh as the first line. Conventional
is name.sh |
For mathematical expressions, use the
expr command. Remember to escape special characters (like
* for multiplication as \*). |
|
Special characters and Names |
I/O redirection |
cmd<handle |
redirect input to handle |
cmd>handle |
redirect output to handle |
cmd>>file |
append to file |
&0 |
handle for STDIN |
&1 |
handle for STDOUT |
&2 |
handle for STERR |
stream>&stream |
redirect stream to stream |
2>file |
redirect STDERR to file |
>&2 |
redirect output to STDERR |
2>&1 |
redirect STDERR to STDOUT |
cmd1|cmd2 |
pipe output of cmd1 to input of cmd2 |
|
Regexen for filename expansion |
* |
any number of chars, exept leading . and
/., / |
? |
one char |
[ac-e] |
char a, c, d, or e. |
[!ab] |
not char a or b |
|
User-defined variables |
To export variable names from the
script to the environment use export (instead of setenv
like in csh). |
varname='value' |
Assignment of value to variable. No space around
equals sign! The quotes are optional for simple words.
varname= assigns "" (empty string). Example for settimg
and exporting DISPLAY: DISPLAY=10.203.1.101:0.0; export
DISPLAY |
$varname |
Using a variable. |
${varname} |
Using a variable, braced form if end of varname is
ambiguous. Is undef if no assignment happened. |
${varname:-word} |
Using a variable, or word, if it is undef or
empty. |
${varname:=word} |
Using a variable, after assigning word, if it is
undef or empty. |
${varname/pattern/string} |
Replace pattern with string in the value of
varname. |
|
Automatic variables |
$1 to $9 |
args (params) 1-9 for the script. |
$0 |
the script name |
$# |
number of parameters |
$@ |
the list of all parameters as a list |
$* |
the list of all parameters as one string |
$? |
errorlevel of last command |
$! |
PID of last background process |
$$ |
PID of current process |
Quoting |
'...' |
noninterpolated string |
"..." |
$name, `cmd` and \ interpolated string |
`cmd` |
command substitution replaces command with its
output |
|
Various |
# |
turns the rest of the line into a comment |
cmd& |
run cmd in background |
cmd1 && cmd2 |
cmd2 only executes, when cmd1 returns success |
cmd1 || cmd2 |
cmd2 only executes, when cmd1 returns failure |
\ |
Escape. Concatenates lines. |
|
Examples |
Quoting/Redirection |
chmod 755 `find . -type d` |
change rights for dirs under . |
rm `find . -name "*.html~"` |
remove all .html~ files in dir tree |
|
find . -name "*.html~" -exec rm {} \; ditto, but can handle whitespace in file names
bash
To write special characters under bash, you can use the usual shortcuts, like \t for tab, when you quote them with single quotes lead by a dollar sign, such as this: $'\t'. This will then generate a tab character.