CS155 ShellScripts
#! /bin/bash
#! /bin/sh
#! /bin/tcsh
#! /usr/bin/perl
#! /usr/bin/python
bash
only.
#! /bin/bash mkdir 155tmp touch 155tmp/helloWorld echo "Lala it’s Saturday" > 155tmp/satdaze cat 155tmp/satdaze date
test
.
test
, and the shell will
run that test
, and not your test
.
./whatever
.
,
your current directory.
#! /bin/bash dir=155tmp mkdir $dir touch $dir/helloWorld echo "Lala it’s Saturday" > $dir/satdaze cat $dir/satdaze date
=
value
name=Jack
let
varName=
expression
let age=2024-1957
$
varName
=$(
command)
size=$(wc -c <monster)
% alpha=beta % echo $alpha beta % gamma=2+2 % echo $gamma 2+2 % let delta=2+2 % echo $delta 4 % epsilon=$(date | cut -c5-7) % echo $epsilon Nov % iota=alpha % echo $iota alpha % pi=$alpha % echo $pi beta
% echo $USER cs155 % echo $USERtmp % echo ${USER}tmp cs155tmp % echo $USER-tmp cs155-tmp
Unambiguously designate a variable name: ${var}
Variable | Meaning |
---|---|
$# | how many arguments were given to the script |
$0 | the name of the program |
$1 | the first argument |
$2 | the second argument |
$* | All the arguments in a single string, like "$1 $2 $3 ..." |
$@ | All the arguments in separate strings, like "$1" "$2" "$3" ... |
$? | 0 if the previous command succeeded |
How do you tell if $2
exists?
#! /bin/bash if [[ $# -ne 1 ]] then echo "Usage: $0 file" exit 1 fi ls -l $1
zot
like this: ./zot
./zot x
./zot x y z
./zot hello 543
results in:
$0
= ./zot
$1
= hello
$2
= 543
% echo $UID 2543 % let x="UID*2" % echo $x 5086
All numeric values in the shell are integers. There is no fractional part.
let
name=expr let x="100/(2*3+4)"
We might want to execute a command if a condition is true (or false).
if [[ expr ]] then command command fi
if [[ expr1 ]] then command1 elif [[ expr2 ]] then command2 else command3 fi
if [[ expr ]] then command1a command1b else command2a command2b fi
if [[ $1 -le 0 || $2 -le 0 ]] then echo "All arguments must be positive." exit 1 fi let age=66 sex="M" if [[ age -ge 21 && $sex = "M" ]] then echo "Voter in 1916!" fi if [[ ! ($sex = "M") ]] then echo "Hello, ma’am!" fi
&&
means “and” (both halves must be true)
||
means “or” (one half or the other half or both halves must be true)
!
means “not”
let age=21 let cash=10 let looks=4 let drunk=0 if [[ age -ge 21 && (cash -ge 8 || looks -gt 5) && drunk -eq 0 ]] then echo Consume in moderation. else echo No drink for you! fi
Consume in moderation.
Conditional examples:
% cat scrpt #! /bin/bash if [[ $HOSTNAME = "denver" ]] then echo "Mile high!" elif [[ $HOSTNAME = "lansing" ]] then echo "Welcome to the mitten state!" else echo "Where am I?" fi % ls -l scrpt -rwx------ 1 cs155 class 193 Nov 23 17:06 scrpt % ./scrpt Where am I?
#! /bin/bash grep "foo" xyz >dummy if [[ $? -eq 0 ]] then echo "Hooray, we found foo in the file xyz!" else echo "Sorry, foo was not found in the file xyz." fi rm dummy # be tidy
Why didn’t we rm dummy
immediately after creating it?
We don’t need its contents—why not get rid of it as soon as possible?
if [[ COLUMNS -lt 80 ]] then echo "This terminal is too narrow." echo "It’s only $COLUMNS characters wide." echo "This program requires at least 80 characters." fi
A $
is not required on variables when doing numeric comparisons.
You still need a $
when comparing strings.
Here’s how to compare strings (not numbers):
a = b | does a equal b ? |
a != b | does a not equal b ? |
a < b | is a less than b ? |
a > b | is a greater than b ? |
Surprisingly, there are no ≤
or ≥
operators.
Remember: spaces around operators!
Here’s how to compare numbers:
a -eq b | does a equal b ? |
a -ne b | does a not equal b ? |
a -lt b | is a less than b ? |
a -gt b | is a greater than b ? |
a -le b | is a ≤ b ? |
a -ge b | is a ≥ b ? |
Remember: spaces around operators!
a && b | are both a and b true? |
a | | b | are either a or b true? |
! a | is a false? |
Remember spaces around operators!
#! /bin/bash let hour=$(date "+%k") # 0–23 if [[ hour -lt 12 ]] # Is it 0–11? then echo "Good morning!" elif [[ hour -lt 18 ]] # Is it 12–17? then echo "Good afternoon!" else # Is it 18–23? echo "Good evening!" fi
#! /bin/bash # $1 is the first argument to this program. # $2 is the second argument to this program. # $3 is the third argument to this program. if [[ $1 -eq $2 && $2 -eq $3 ]] then echo "They are all the same!" else echo "This is no good—they’re different." fi
if [[ -d my_file ]] then rmdir my_file fi if [[ -e my_file ]] then echo "my_file still exists" fi
-r
: test if file is readable
-w
: test if file is writable
-x
: test if file is executable
-e
: test if file exists
-d
: test if file is a directory
-s
: test if file has non-zero size
If the world were consistent, life would be much easier.
In the following examples, spaces
look
like
this.
Spaces are nearly forbidden in a let
statement:
let a=b+c/2
Spaces are required in an if
statement:
if [[ $a -eq 42 ]]