Frank Schacherer Homepage
home technology bibliography

Unix /bin/sh Refcard

[Guard.]

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