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