From 5a265a0ce6b1793a879bd227fa9b24ebd08fd15c Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Sun, 01 Apr 2012 03:42:44 -0400 Subject: Move UNIX shell workshop files under guides. --- (limited to 'guides/shell-workshop') diff --git a/guides/shell-workshop/flyer.pdf b/guides/shell-workshop/flyer.pdf new file mode 100644 index 0000000..ab0da8b --- /dev/null +++ b/guides/shell-workshop/flyer.pdf Binary files differ diff --git a/guides/shell-workshop/flyer.svg b/guides/shell-workshop/flyer.svg new file mode 100644 index 0000000..0596252 --- /dev/null +++ b/guides/shell-workshop/flyer.svg @@ -0,0 +1,225 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + UNIX® Shell Scripting Workshop + Introduction to the UNIX ShellLanguage and Environment + + + $ cat /etc/motdThis workshop is applicable toany standards-compliant shell onany UNIX-like operating system, such as GNU Bashon GNU/Linux, tcsh on Oracle® Solaris (as usedfor NJIT AFS), or GNU Bash on Apple® Mac OS X®. + $ who am iPatrick "P. J." McDermottmailto:pjm28@njit.eduStudent, BS Computer ScienceLeader, NJIT ACM SIG GNU/Linux + $ whereis workshopWed, March 28 6:00 PM - 8:30 PM WEST LECT 2Fri, March 30 1:00 PM - 3:30 PM CULM LECT 2 + + + + + + + diff --git a/guides/shell-workshop/index.html b/guides/shell-workshop/index.html new file mode 100755 index 0000000..de75f24 --- /dev/null +++ b/guides/shell-workshop/index.html @@ -0,0 +1,77 @@ + + +

UNIX® Shell Scripting Workshop

+

Introduction to the UNIX Shell Language and Environment

+

+ This is a workshop that I gave at the New Jersey Institute of Technology + (NJIT) in the Spring of 2012 as part of the workshop series of the + university's chapter of the Association for Computing Machinery (ACM). It + was based on a similar tutorial I had given during meetings of NJIT ACM's + SIG GNU/Linux in the Fall of 2011. +

+

Flyer

+

+ Below you may find the flyer for this event: +

+ +

+ Copyright © 2012 Patrick "P. J." McDermott +
+ This flyer may be used under the terms of the + Creative Commons + Attribution 3.0 Unported license.
+ This flyer includes copyrighted images used pursuant to the fair use + limitation of U.S. Copyright Law. +

+

Standards

+

+ The workshop referred to the Shell and Utilities (XCU) volume of + POSIX.1-2008, + published by the IEEE and The Open Group. + Everything covered applies to any sufficiently-compliant shell and operating + system. +

+

Notes

+

+ The following are my notes from the tutorial I gave at SIG GNU/Linux + meetings, reused for the workshop: +

+ +

+ The following are the notes I wrote as a guide for the workshop: +

+ +

Session

+

+ The following is a cleaned-up version of the shell session from the + workshop, including all of the commands I ran and scripts I wrote. +

+ +

Examples

+

+ At the end of the workshop, I showed the following example shell scripts: +

+ + diff --git a/guides/shell-workshop/notes.txt b/guides/shell-workshop/notes.txt new file mode 100644 index 0000000..f630f2a --- /dev/null +++ b/guides/shell-workshop/notes.txt @@ -0,0 +1,137 @@ +introduction +shell + interface available on any UNIX-like OS + interesting: both UI and API +shell input [XCU 2.1] + specified file + '-c' option argument + stdin (interactive mode) +first steps: `echo` command [XCU 4] +ex. 1: Hello world + demonstration of input methods + ex. 1.1: + [sh] + $ echo Hello world + ex. 1.2: + [hello.sh] + echo Hello world + [sh] + $ sh hello.sh + ex. 1.3: + [sh] + $ sh -c 'echo Hello world' +magic number behavior, `chmod` [XCU 4], file modes +ex. 2: magic hello + [hello-magic.sh] + #! /bin/sh + echo Hello world + [sh] + $ chmod a+x + $ sh hello-magic.sh +field splitting [XCU 2.6.5] +simple commands: `cd`, `ls`, `mkdir`, `touch` [XCU 4] +ex. 3: field splitting + [sh] + $ mkdir foo bar + $ ls +tilde expansion [XCU 2.6.1] +ex. 4: tilde expansion + [sh] + $ ls ~ + $ ls ~sh-foo + $ ls ~sh-foo/some-directory +pathname expansion [XCU 2.6.6] [XCU 2.13] +ex. 5: pathname expansion + [sh] + $ echo ~sh-foo/*-file + $ echo ~sh-foo/ba*/file +parameters: assignment +ex. 6: parameter assignment + [sh] + $ myparam=foo + $ mynum=1 +parameters: expansion [XCU 2.6.2] + simple parameter + use default values + string length + remove {smallest,largest} suffix pattern + remove {smallest,largest} prefix pattern +ex. 7: parameter expansion + [sh] + $ echo ${myparam} + $ echo ${nullparam:-default} + $ echo ${#myparam} + $ file=main.c + $ echo ${file%.c}.o + $ dir=foo/bar/baz + $ echo ${dir##*/} +positional parameters [XCU 2.5.1] +ex. 8: positional parameters + [pos-params.sh] + #! /bin/sh + echo ${1} + echo ${2} + [sh] + $ chmod a+x pos-params.sh + $ sh pos-params.sh foo + $ ./pos-params.sh foo bar baz +special parameters [XCU 2.5.2] + @, *, #, ?, 0 +exit status [XCU 2.8.2] +`false` and `true` commands [XCU 4] +ex. 9: special parameters + [spec-params.sh] + #! /bin/sh + echo Number of positional parameters: ${#} + echo Positional parameters: ${@} + echo Script name: ${0} + true + echo ${?} + false + echo ${?} + [sh] + $ chmod a+x spec-params.sh + ./spec-params.sh foo bar baz +shell variables [XCU 2.5.3] + HOME, IFS, PATH, PS1, PWD +ex. 10: shell variables + [sh] + $ echo ${HOME} + $ echo ${PWD} + [sh (another shell)] + $ PS1='$ ' + $ PS1='PROMPT> ' +command substitution [XCU 2.6.3] + two versions +ex. 11: command substitution + [sh] + $ filepath=$(basename ~sh-foo/bar/file) + $ echo ${filepath} +arithmetic expansion [XCU 2.6.4] +ex. 12: arithmetic expansion + $ echo $((2+3)) + $ echo $((0x10 + 4)) + $ i=0 + $ i=$(($x + 1)) + $ echo ${i} +basic foundation complete +simple commands revisited [XCU 2.9.1] + simple-command: [parameter-assignment...] [word...] + command search and execution +pipelines [XCU 2.9.2] +lists [XCU 2.9.3] + AND-OR list + list +ex. 13: lists + [sh] + $ false && echo foo || echo bar + $ true || echo foo && echo bar +compound commands [XCU 2.9.4] + grouping + if, `test` command + while + until + for + case +functions [XCU 2.9.5] +I/O redirection [XCU 2.7] diff --git a/guides/shell-workshop/session.html b/guides/shell-workshop/session.html new file mode 100644 index 0000000..1a5da6e --- /dev/null +++ b/guides/shell-workshop/session.html @@ -0,0 +1,381 @@ +

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
+
diff --git a/guides/shell-workshop/session.txt b/guides/shell-workshop/session.txt new file mode 100644 index 0000000..234c240 --- /dev/null +++ b/guides/shell-workshop/session.txt @@ -0,0 +1,381 @@ +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 < this is input + > some more input + > EOF + Line: this is input + Line: some more input diff --git a/guides/shell-workshop/shell-tut.txt b/guides/shell-workshop/shell-tut.txt new file mode 100644 index 0000000..0a73cb0 --- /dev/null +++ b/guides/shell-workshop/shell-tut.txt @@ -0,0 +1,126 @@ +first steps and basic output + how shell reads input - three methods + use of "echo" built-in utility + ex: hello world +simple commands, field splitting, and quoting + ex: maybe cd, mkdir/touch, etc. +tilde and pathname expansion + ex: cd with tildes + ex: cd/mkdir/touch with pathname expansions +parameters + defining variables and expanding their values + positional parameters, special parameters, and shell variables + ex: assign variables + ex: expand and print variables and positional parameters +command substitution + ex: commands in subshells, output assigned to variables +arithmetic expansion + ex: some expressions, assignments, etc. +shell commands + revisit simple commands + command search and execution + pipelines + lists + sequential + asynchronous + AND + OR + compound commands + grouping + subshell vs current shell, shell execution environment: + open files + working directory + shell parameters + shell functions + shell options + shell aliases + if + show "test"/"[" command + while + ex: loop over positional parameters + #! /bin/sh + while [ $# -gt 0 ]; do + printf '%s\n' "$1" + shift + done + ex: read from input + until + for + case + functions +exit status +I/O redirection +built-in utilities + colon + export + break [n] + continue [n] + dot + eval + exec + exit + export + return + set + shift + unset +utilities + cat + cd + chgrp + chmod + chown + cp + date + dd + df + diff + dirname + du + echo + expr + false + file + fold + getopts + grep + head + id + kill + ln + lp + ls + mailx + mesg + mkdir + mkfifo + more + mv + nice + pr + printf + ps + pwd + read + rm + rmdir + sed + sh + sleep + sort + stty + tail + test + time + touch + tr + true + uniq + wc + who + +example scripts: + screen-batt + /usr/local/lib/pjrand.sh and /usr/local/bin/screensaver + /bin/which of Debian (ex. of IFS) + changelog-gen diff --git a/guides/shell-workshop/shell.txt b/guides/shell-workshop/shell.txt new file mode 100644 index 0000000..d98d249 --- /dev/null +++ b/guides/shell-workshop/shell.txt @@ -0,0 +1,131 @@ +introduce the shell interpreter + POSIX.1-2008 XCU 2.1 + shell reads input from: + a specified file, + '-c' option argument, or + stdin (interactive mode) + shell splits input lines into tokens and parses them + shell expands words + shell performs I/O redirection + shell executes functions, built-in commands, files, etc. +parameters and variables + positional parameters + POSIX.1-2008 XCU 2.5.1 + decimal numbers greater than 0, e.g. $1 and $2 + multiple-digit numbers should be enclosed in braces + assigned with: + shell arguments when shell starts + function arguments when a function is called + can be reassigned using 'set' built-in command + special parameters + POSIX.1-2008 XCU 2.5.2 + @ + all positional parameters + * + all positional parameters + # + number of positional parameters + ? + exit status of most recent command pipeline + - + current option flags + $ + process ID of shell + ! + process ID of most recent background command + 0 + name of shell or shell script + shell variables + POSIX.1-2008 XCU 2.5.3 + HOME + pathname of user's home directory + IFS + delimiters for field splitting + default: + LINENO + line number of current script, if any + PATH + list of paths which should be searched for commands + PS1 + prompt value to be expanded and written to standard error + default value: "$ " + PWD + absolute pathname of the current working directory +word expansions + tilde expansion + POSIX.1-2008 XCU 2.6.1 + tilde-prefix: unquoted tilde at the beginning of a word + followed by all unquoted characters until first unquoted slash + login name is all characters in tilde-prefix following tilde + if login name is empty (tilde-prefix == "~") + expanded to value of HOME + else + expanded to home directory associated with login name + parameter expansion + POSIX.1-2008 XCU 2.6.2 + ${expression} or $expression + expression: + parameter + parameter:-word + parameter:=word + parameter:?word or parameter:? + parameter:+word + #parameter + parameter%word + parameter%%word + parameter#word + parameter##word + command substitution + POSIX.1-2008 XCU 2.6.3 + $(command) + or + `command` + expanding: + shell executes command in a subshell + shell replaces substitution with stdout of the command + newlines within command are allowed + nesting + `command1 \`command2 foo\` bar` + $(command1 $(command2 foo) bar) + arithmetic expansion + POSIX.1-2008 XCU 2.6.4 + $((expression)) + expanding: + shell processes expression + shell replaces substitution with value of the expression + arithmetic: + signed long integer precision + decimal, octal, and hexadecimal constants + e.g. 42, 052, 0x2A + operators: + ( ), unary +, unary -, +, -, *, /, % + ~, !, <<, >>, &, ^, | + <, <=, >, >= ==, !=, &&, ||, expr ? expr : expr + =, +=, -=, *=, /=, %=, <<=, >>=, &= ^=, |= + shell variables + if x has an integer value, then the following are equivalent: + $((x + 1)) $(($x + 1)) + field splitting + POSIX.1-2008 XCU 2.6.5 + IFS is a set of delimiters, at which unquoted fields are split + pathname expansion + POSIX.1-2008 XCU 2.6.6 + POSIX.1-2008 XCU 2.13 + performed unless 'set -f' was run + patterns + ? matches any single character + * matches multiple (0 or more) characters + [ opens RE bracket expansion + if pattern does not match any existing files + pattern string is left unchanged +redirection + input redirection + [n]word + [n]>|word + n default: 1, stdout + appending redirected output + [n]>>word -- cgit v0.9.1