Shell Input
sh@sleipnir1:~$ vim hello.sh
sh@sleipnir1:~$ cat hello.sh
echo Hello world
sh@sleipnir1:~$ sh hello.sh
Hello world
sh@sleipnir1:~$ sh -c 'echo Hello world'
Hello world
sh@sleipnir1:~$ echo Hello world
Hello world
Comments, Magic Number Behavior, and File Modes
sh@sleipnir1:~$ vim hello.sh
sh@sleipnir1:~$ cat hello.sh
#! /bin/sh
# This is a comment
echo Hello world
sh@sleipnir1:~$ ./hello.sh
-su: ./hello.sh: Permission denied
sh@sleipnir1:~$ ls -l hello.sh
-rw-r--r-- 1 sh sh 48 Mar 30 13:26 hello.sh
sh@sleipnir1:~$ chmod a+x hello.sh
sh@sleipnir1:~$ ls -l hello.sh
-rwxr-xr-x 1 sh sh 48 Mar 30 13:26 hello.sh
sh@sleipnir1:~$ ./hello.sh
Hello world
Field Splitting and Quoting
sh@sleipnir1:~$ mkdir foo bar
sh@sleipnir1:~$ ls
bar foo hello.sh
sh@sleipnir1:~$ rmdir foo bar
sh@sleipnir1:~$ mkdir foo\ bar
sh@sleipnir1:~$ ls
foo bar hello.sh
sh@sleipnir1:~$ rmdir foo\ bar
sh@sleipnir1:~$ ls
hello.sh
sh@sleipnir1:~$ mkdir 'foo bar
> baz'
sh@sleipnir1:~$ ls
foo bar?baz hello.sh
sh@sleipnir1:~$ rmdir 'foo bar
> baz'
sh@sleipnir1:~$ ls
hello.sh
sh@sleipnir1:~$ mkdir "foo bar baz"
sh@sleipnir1:~$ ls
foo bar baz hello.sh
Tilde Expansion
sh@sleipnir1:~$ echo ~
/home/sh
sh@sleipnir1:~$ ls ~sh-foo
another-directory another-file bar baz foo some-directory some-file
sh@sleipnir1:~$ ls ~sh-foo/some-directory
Hey, this is a cool file!
Pathname Expansion
sh@sleipnir1:~$ echo ~sh-foo/*-file
/home/sh-foo/another-file /home/sh-foo/some-file
sh@sleipnir1:~$ echo ~sh-foo/ba*/file
/home/sh-foo/bar/file /home/sh-foo/baz/file
sh@sleipnir1:~$ echo ~sh-foo/ba[a-r]/file
/home/sh-foo/bar/file
sh@sleipnir1:~$ echo ~sh-foo/ba[p-z]/file
/home/sh-foo/bar/file /home/sh-foo/baz/file
Parameter Assignment
sh@sleipnir1:~$ myparam=foo
sh@sleipnir1:~$ mynum=1
Parameter Expansion
sh@sleipnir1:~$ echo ${myparam}
foo
sh@sleipnir1:~$ echo ${nullparam:-default}
default
sh@sleipnir1:~$ echo ${#myparam}
3
sh@sleipnir1:~$ file=main.c
sh@sleipnir1:~$ echo ${file%.c}.o
main.o
sh@sleipnir1:~$ dir=foo/bar/baz
sh@sleipnir1:~$ echo ${dir##*/}
baz
Positional Parameters
sh@sleipnir1:~$ vim pos-params.sh
sh@sleipnir1:~$ cat pos-params.sh
#! /bin/sh
echo ${1}
echo ${2}
sh@sleipnir1:~$ chmod a+x pos-params.sh
sh@sleipnir1:~$ ./pos-params.sh foo
foo
sh@sleipnir1:~$ sh pos-params.sh foo bar baz
foo
bar
Special Parameters
sh@sleipnir1:~$ vim spec-params.sh
sh@sleipnir1:~$ cat spec-params.sh
#! /bin/sh
echo Number of positional parameters: ${#}
echo Positional parameters: ${@}
echo Script name: ${0}
sh@sleipnir1:~$ sh spec-params.sh foo bar baz
Number of positional parameters: 3
Positional parameters: foo bar baz
Script name: spec-params.sh
Exit Statuses
sh@sleipnir1:~$ vim spec-params.sh
sh@sleipnir1:~$ cat spec-params.sh
#! /bin/sh
echo Number of positional parameters: ${#}
echo Positional parameters: ${@}
echo Script name: ${0}
true
echo ${?}
false
echo ${?}
sh@sleipnir1:~$ sh spec-params.sh foo bar baz
Number of positional parameters: 3
Positional parameters: foo bar baz
Script name: spec-params.sh
0
1
Shell Variables and Links .
and ..
sh@sleipnir1:~$ echo ${HOME}
/home/sh
sh@sleipnir1:~$ echo ${PWD}
/home/sh
sh@sleipnir1:~$ ls
foo bar baz hello.sh pos-params.sh spec-params.sh
sh@sleipnir1:~$ cd foo\ bar\ baz/
sh@sleipnir1:~/foo bar baz$ echo ${PWD}
/home/sh/foo bar baz
sh@sleipnir1:~/foo bar baz$ ls .
sh@sleipnir1:~/foo bar baz$ mkdir file1 file2
sh@sleipnir1:~/foo bar baz$ ls .
file1 file2
sh@sleipnir1:~/foo bar baz$ ls ..
foo bar baz hello.sh pos-params.sh spec-params.sh
sh@sleipnir1:~/foo bar baz$ cd ..
sh@sleipnir1:~$ echo ${PWD}
/home/sh
sh@sleipnir1:~$ PS1='$ '
$ PS1='PROMPT> '
PROMPT> echo Hello
Hello
PROMPT> PS1='$ '
$ echo Hello \
> World
Hello World
Command Substitution
$ filepath=$(basename ~sh-foo/bar/file)
$ echo ${filepath}
file
Arithmetic Expansion
$ echo $((2+3))
5
$ echo $((0x10 + 4))
20
$ i=0
$ i=$(($i + 1))
$ echo ${i}
1
$ i=$(($i + 1))
$ echo ${i}
2
$ i=$(($i + 1))
$ echo ${i}
3
Simple Commands
$ i=0 echo Hello
Hello
Command Search and Execution
$ echo ${PATH}
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
$ ./hello.sh
Hello world
$ hello.sh
-su: hello.sh: command not found
$ ls
foo bar baz hello.sh pos-params.sh spec-params.sh
$ PATH=${PATH}:${HOME}
$ echo ${PATH}
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/home/sh
$ hello.sh
Hello world
Pipelines
$ ! true
$ echo ${?}
1
$ ! false
$ echo ${?}
0
$ true
$ echo ${?}
0
$ false
$ echo ${?}
1
Lists
$ false && echo foo || echo bar
bar
$ true || echo foo && echo bar
bar
test
Command and if
Construct
$ [ foo = foo ] && echo equal || echo not equal
equal
$ if [ foo = foo ]; then echo equal else echo not equal; fi
equal else echo not equal
$ if [ foo = foo ]; then echo equal; else echo not equal; fi
equal
$ if [ foo = foo ]; then
> echo equal
> else
> echo not equal
> fi
equal
while
Loop
$ i=0
$ while [ ${i} -lt 5 ]; do
> echo ${i}
> i=$(($i + 1))
> done
0
1
2
3
4
$ vim param-loop.sh
$ cat param-loop.sh
while [ ${#} -gt 0 ]; do
echo Parameter: ${1}
shift
done
$ sh param-loop.sh foo bar baz
Parameter: foo
Parameter: bar
Parameter: baz
for
Loop
$ for param in foo bar baz; do
> echo ${param}
> done
foo
bar
baz
case
Construct
$ param=foo
$ case ${param} in
> f*)
> echo starts with f
> ;;
> b*)
> echo starts with b
> ;;
> esac
starts with f
Functions
$ print_hello()
> {
> echo Hello world
> }
$ print_hello
Hello world
$ print_params()
> {
> echo ${@}
> }
$ print_params 1 2 3
1 2 3
Input/Output Redirection
$ echo Hello world > hello-file
$ cat hello-file
Hello world
$ echo Hello world > hello-file
$ echo Hello world > hello-file
$ echo Hello world > hello-file
$ cat hello-file
Hello world
$ echo Hello world >> hello-file
$ echo Hello world >> hello-file
$ cat hello-file
Hello world
Hello world
Hello world
$ vim read-file.sh
$ cat read-file.sh
while read line; do
echo Line: ${line}
done < myfile.txt
$ sh read-file.sh
Line: line one
Line: line two
Line: some other line
$ vim read-file.sh
$ cat read-file.sh
while read field1 field2; do
echo Line: ${field1}, ${field2}
done < myfile.txt
$ sh read-file.sh
Line: line, one
Line: line, two
Line: some, other line
$ echo Hello world > /dev/null
$ sh -c not-a-command
sh: 1: not-a-command: not found
$ sh -c not-a-command 2> /dev/null
$ while read line; do
> echo Line: ${line}
> done <<EOF
> this is input
> some more input
> EOF
Line: this is input
Line: some more input