Unix Shell Script

 

IO

Standard IOs

0 stdin
1 stdout
2 stderr

IO Redirects

# Redirect stdout to a file:
1>filename
echo "test" 1>stdout.txt
 
# Redirect stdout and append to a file:
1>>filename
 
# Redirect stderr to a file:
2>filename
 
# Redirect stderr and append to a file:
2>>filename
 
# Redirect both stdout and stderr to a file:
&>filename
 
# Send stderr to stdout
2>&1	
 
# Redirect file descriptor i to j
i>&j
 
# Redirect i to j
>&j = 1>&j	
 
# Close stdin
<&-
 
# Close stdout
>&-
 
# Read stdin from file
0<filename
<filename	grep "test" < test.txt

Loop Structures

For Loop

for i in 'ls | grep jar'
do
	echo "$i"
done

While Loop

i=1
while [ "$i" -le 5 ]
do
	echo "$i"
	i='expr $i + 1'
done

Condition

If Condition

if [ ]
then
  # do something
elif [ ]
then
  # do something
else
  # do something
fi

Logical and

* If cmd1 succeeds go to cmd2
cmd1 && cmd2

Logical or

* If cmd1 fails then go to cmd2
cmd1 || cmd2

Test File Operators

-b FILE # FILE exists and is block special
-c FILE # FILE exists and is character special
-d FILE # FILE exists and is a directory
-e FILE # FILE exists
-f FILE # FILE exists and is a regular file
-g FILE # FILE exists and is set-group-ID
-G FILE # FILE exists and is owned by the effective group ID
-h FILE # FILE exists and is a symbolic link (same as -L)
-k FILE # FILE exists and has its sticky bit set
-L FILE # FILE exists and is a symbolic link (same as -h)
-O FILE # FILE exists and is owned by the effective user ID
-p FILE # FILE exists and is a named pipe
-r FILE # FILE exists and read permission is granted
-s FILE # FILE exists and has a size greater than zero
-S FILE # FILE exists and is a socket
-t FD # File descriptor FD is opened on a terminal
-u FILE # FILE exists and its set-user-ID bit is set
-w FILE # FILE exists and write permission is granted
-x FILE # FILE exists and execute (or search) permission is granted

Test Integer Operators

-eq
-ne
-gt
-ge
-lt
-le

String Comparison

[ s1 = s2 ]  # s1 equals to s2
[ s1 == s2 ] # synonym for =
[ s1 != s2 ] # s1 not equal to s2
[ s ]        # is not null
[ -n s ]     # s is not null
[ -z s ]     # s is null

Boolean Operators

! not
-a and
-o or

Variables

Naming

* Begins with an alphabetic or underscore character
* Followed by zero or more alphanumeric or underscore characters
* No spaces

Declare

* No data type concept
* No need to declare

Assign

* var=val # Notice no spaces before or after equal sign

Access

* $var
* ${var}

De-referencing

* Use eval derefVar=\$$var to do de-referencing.
* After de-referencing, derefVar will contain value referenced by $var.

#!/usr/bin/sh
var1=VariableOne
echo "\$var1=$var1"
 
var2=var1
echo
echo "Before dereferencing..."
echo "\$var2=$var2"
 
echo
echo "After dereferencing..."
eval derefVar2=\$$var2
echo "\$derefVar2=$derefVar2"
 
# Result:
$var1=VariableOne
 
Before dereferencing...
$var2=var1
 
After dereferencing...
$derefVar2=VariableOne

Arithmetic on Shell Variables

* Operators: + – * / %
* Need spaces around input numbers.
* Need to escape * character.
* Examples:

expr 1 + 2
3

# If no spaces around input numbers:
expr 1+2
1+2

# Need to escape *
$ expr 2 \* 2
4

# Otherwise
$ expr 2 * 2
expr: syntax error

# Assign result
$ i=1
$ i=`expr $i + 1`    # Notice the back quotes
$ echo $i
2

Built-in Variables

$0: name of calling prog
$1 $2…: each individual argument
$*: all arguments
$@: a list of separate arguments
$$: pid of the process being exceed # Good for temp file name
$?: exit status
$#: count of args

Built-in Shell Parameters

IFS=”:” Internal field separater
HOME
MAIL
MAILCHECK
PS1
PS2
SHELL

Special characters

\010  Backspace
\011  Tab
\012  New line character
\013  Line feed
\014  Form feed
\015  CR character
\033  Escape

Backslash

* As an escape character:

$ echo \\
\
$ echo \$x
$x

* For continuing lines when used as last character on the line:

$ lines=one'     # Single quotes tell shell to ignore newline
> 'two
$ echo $lines
one two

$ lines=one\
> two
$ echo $lines
onetwo

Quotes

Single Quotes

* Ignore all quoted characters, for example:

$ echo '<> | / \ ` $'
<> | / \ ` $

Double Quotes

* ignore most enclosed characters except $, \ (backslash), ` (back quotes).
* Examples:

$ name=jim

$ echo "name: ${name}"
name: jim

$ echo "name: \${name}"
name: ${name}

$ echo `date`
Thu May 28 12:34:58 EDT 2009

Backquotes

* Execute command:

$ echo `date`
Thu May 28 12:34:58 EDT 2009

* Result reformatted into one line

Function

* Example

#!/usr/bin/bash
 
fxn1 () {
  if [ $# -ne 1 ]; then
    echo "Please provide one argument."
    exit 1
  else
    echo "Got argument via \$1: $1"
  fi
 
  if [ $1 = "ok" ]; then
    echo "Got ok"
    return 0
  else
    echo "Not ok"
    return 1
  fi
}
 
echo
echo "Calling fxn1 with argument..."
fxn1 ok
echo "\$?: $?"
echo
echo "Calling fxn1 with argument..."
fxn1 notok
echo "\$?: $?"
echo
echo "Calling fxn1 without argument..."
fxn1

* Result

 
Calling fxn1 with argument...
Got argument via $1: ok
Got ok
$?: 0
 
Calling fxn1 with argument...
Got argument via $1: notok
Not ok
$?: 1
 
Calling fxn1 without argument...
Please provide one argument.

read command

#!/bin/sh
echo "delete...?"
read ok
if [ "$ok" = "y" ]; then
	echo "file name?"
	read file_to_del
	echo "deleting..."
	rm $file_to_del
	echo "done."
else
	echo "none deleted"
	exit 1
fi

basename and dirname

* basename /this/is/a/dir/file gives file
* dirname /this/is/a/dir/file gives /this/is/a/dir

trap

trap “” 15
0 Exit from shell
1 Hangup
2 Interrupt
15 Software termination signal

cut

* used for column cutting.

cut -cchars file
where chars specifies what characters to extract 
from each line of file.
 
command                    extracts
who | cut -c5              character 5
who | cut -c1,13,50        characters 1, 13 and 50
who | cut -c20-50          characters 20 throught 50
who | cut -c5-             characters 5 to the end of line 
 
cut

tr

* Translate or replace characters
* Example, replace underscore with space character:

str="str1_str2"; echo $str|tr '_' ' '
str1 str2

Inverse Text

${smso}text${rmso}

Regular expression

Notation    Meaning                  Example        Matches
.           any character            a..            a followed by any two characters

^           beginning of line        ^hello         hello only if it appears at the beginning of the line

$           end of line              friend$        friend only if it appears at the end of the line

*           zero or more             x*             zero or more x's
            occurrence of            xx*            one or more x's
            previous reg exp         .*             zero or more characters

[chars]     any char in chars        [tT]           lower or upper case t
                                     [a-z]          lower case letter
                                     [a-zA-Z]       lower or upper case letter

[^chars]    any char                 [^0-9]         any non-numeric char 
            NOT in chars             [^a-zA-Z]      any non-alphabetic char

\{min,max\} at least min and         x\{1,5\}       at least 1, at most 5 x's
            at most max occurrences  [0-9]\{3,9\}   3 to 9 consecutive digits
            of previous reg exps     [0-9]\{3\}     exactly 3 digits
                                     [0-9]\{3,\}    at least 3 digits

\(...\)     store char matched       ^\(.\)         first char in line and stores it in register 1
            between parentheses      ^\(.\)\1       first two characters in line if they're the same
            in next register (1-9).                 
            retrieve register with
            \n. e.g. \1 retrieves
            values stored in first
            register

GNU find

Syntax

find \
[-P] \ # Never follow symbolic link. This is default.
[-L] \ # Follow symbolic link.
[-H] \ # Do not follow symbolic link except when processing command line arguments.
[path…] \

-daystart \ # Measure times from the beginning of the day instead of default 24 hrs ago.
-depth \ # Process directory contents first
-d \ # same as -depth
-help \
-maxdepth \ # Descent at most levels. -maxdepth 0 mean current dir
-mindepth \ # Start find only at designated levels. -mindepth 1 excludes command line dir.
-mount \ # Do not descent directories in other file systems
-noleaf \ # Do not assume Unix filesystem to accommodate CDROM etc
-regextype type \ # Default to emac
-version \
-warn, -nowarn \ # Turn warning on and off
-xdev \ # Same as -mount

# +n: greater than, -n: less than, n: exactly n
-amin n \ # File last accessed n minutes ago
-anewer file \
-atime n \ # Access n*24 hours ago
-cmin n \ # Last changed n minutes ago
-cnewer file \
-ctime n \
-empty \ # File is empty
-fstype type \
-gid n \ # File numeric group id is n
-group gname \ # File belongs to gname group name
-ilname \ # Like -lname but case insensitive
-iname \ # Like -name but case insensitive
-iregex \ # Like -regex but case insensitive
-links n \ # File has n links
-lname pattern \ # Symbolic links matching pattern
-mmin n \ # Last modified n minutes ago
-mtime n \ # Last modified n*24 minutes ago
-name pattern \
-newer file \ # Last modified newer than file
-nouser \
-nogroup \
-path pattern \
-perm mode \
-perm -mode \
-regex pattern \
-samefile name \
-size n[cwbkMG] \
-type [bcdpflsD] \ # Type of byte, char, dir, pipe, file, link,socket,door (Solaris)
-uid n \ # Owned by uid of n
-used n \
-user uname \ # Owned by uname
-wholename pattern \ # Matches shell pattern of pattern
-xtype

Examples

find ./ FTP.LOG -exec rm {} \;
 
find / -size +1000000000c;
(look for files larger than 1gb)
 
# Find jpg files
find . -type f -name "*.jpg" -print
 
# Find files larger than 10KB and list their details
find . -type f -size +10000 -exec ls -al {} \;
 
# Find files accessed two days ago and list their details
find . -atime +2 -type f -exec ls -al {} \;
 
# Find files modified 90 days ago and list their details
find . -mtime +90 -type f -exec ls -al {} \;
 
# Find files modified about 10 minutes ago and list their details
  # Find current date time
  >date
  Tuesday, July 13, 2010 02:22:59 PM GMT
 
  # Create an empty anchor file with time stamp set to 10 min ago
  >touch -t 201007131412 /tmp/mytemptime.tmp 
 
  >ls -l /tmp/mytemptime.tmp
  -rw-r--r--   1 oracle   dba  0 Jul 13 14:12 /tmp/mytemptime.tmp
 
  # Find all files newer than the anchor file
  >find . -type f -newer /tmp/mytemptime.tmp -exec ls -l {} \;
  -rw-r-----   1 oracle   dba  97013 Jul 13 14:25 ./Apache/Apache/logs/access_log.1279022400
 
# Find "admin" string in all properties files
find . -type f -name "*.properties" -exec grep -i "admin" {} \; 
 
# Find "admin" string in all properties files, also list file name
find . -type f -name "*.properties" -print -exec grep -i "admin" {} \; 
 
# Find all *non* zip files
find . -type f \! -name "*.zip" -print
 
# Find *non* zip and *non* txt files
find . -type f \! -name "*.zip" \! -name "*.txt" -print
 
# Find files owned by jboss
find -user jboss
 
# Find files accessed two days ago from today's day start time i.e. 0:00am
find . -atime +2 -daystart
 
# Find properties files in the next two levels of subdirectories.
find . -name "*.properties" -depth -print -maxdepth 2
 
# Find empty files
find . -empty -type f

References

* More Bash Examples

This entry was posted in shell, unix. Bookmark the permalink.