# Presentation: 2QFYONKPG3566U3YFPHXY6T7JLCK6VE4

## Introduction to UNIX

- E-Mail:    nasirc@nasa.gov
- Phone:     1-800-7-NASIRC
- WWW:    http://nasirc.nasa.gov

**Introduction to UNIX**

***NASIRC  presents...***

## NASIRC Contact Information

- Electronic Mail:
- nasirc@nasa.gov
- NASIRC Help Desk:
- (US)  1-800-7NASIRC or 1-800-762-7472
- (Int’l)  1-301-441-4398
- Secured  Phone Line  (STU-III):
- 1-301-982-5480
- 24  Hour Pager:
- 1-800-skypage  pin # 2023056
- FAX #:
- 1-301-441-1853
- U.S. Postal
- Code 630; GSFC; Greenbelt, MD, 20771
- FTP  Archive:
- ftp  nasirc.nasa.gov (restricted to nasa.gov domain)
- NASIRC Homepage:
- http://nasirc.nasa.gov

## Intro to UNIX Syllabus

**History of Unix (pages 7 - 21)**
**Understanding Unix (pages 22 - 24)**
- Basic model (kernel and shell) (page 104, 135)
- Unix themes
- license-plate-jargon
- pipes
- other
**Unix file system and Important directories (pages 30 - 32 and 95)**
**Basic commands (pages 37 - 53, 69 - 73)**
**Ownerships and Permissions (pages 54 - 59)**
**Electronic Mail (pages 82 - 85)**
**Wildcards and Regular Expressions (pages 33 - 36, 74 - 81, 105 - 109)**
**Output Redirection (pages 25 - 29)**
**Processes and Job Control (pages 86 - 90)**
**Files, Devices, and Inodes (pages 96 - 103)**
**Shell Variables (pages 60 - 68)**
**Environment Variables (pages 110 - 120, 136 - 137)**
**Filters (grep, sed, awk, sort) (pages 124 - 134)**
**Shell Scripts (pages 91 - 94, 1201- 123)**
**Advanced Shell Scripting (pages 138 - 154)**
**Aliases and Functions (pages 155 - 159)**

## Table of Contents

- _Subject__	__	_                      _Page #_
- cd and pwd
- 	  Change to Another Directory	39
- mkdir
- 	  Make a New Directory		40
- rmdir
- 	  Remove a Directory		41
- echo
- 	  Print Text on Screen		42
- more
- 	  View a Text File		43
- cat
- 	  Concatenate and Print Files	43
- cat
- 	  Entering Short Files		45
- mv
- 	  Move or Rename Files		46
- mv
- 	  Move or Rename Directories	46
- mv
- 	  Options			48
- rm
- 	  Remove Files		49
- rm
- 	  Recursive Removal		50
- cp
- 	  Copying Files		51
- cp
- 	  Options			52

- _Subject__	__	_                     _Page #_
- What is UNIX?			6
- UNIX History			7
- Vendors and Versions		11
- What makes it UNIX?		12
- 	Multitasking		13
- 	Multiuser			14
- 	Networked
- 	  TCP/IP			15
- 	   uucp			16
- 	Portable			17
- Starting a UNIX Session		18
- 	Logging into UNIX		19
- The Shell			21
- Shell Command Syntax		22
- Options vs Arguments		23
- The Standard Output		24
- The Standard Input		25
- Appending			26
- Standard Error			27
- Pipes and Filters			28
- The UNIX File System		29
- UNIX File Names		30
- The UNIX File System Hierarchy		31
- File Name Expansion (Wildcards)		32
- Wildcard Characters		33
- Common UNIX Commands		36
- 	ls - List Contents of a Directory	37
- 	ls - More Options		38

## Table of Contents

- _Subject__	__	_                      _Page #_
- File Ownership			53
- File Access			54
- chmod			55
- Groups
-  The Old Way			56
- Groups
-  The New Way			57
- Groups
-  Every Which Way		58
- Shell Variables			59
- Important shell variables		60
- Environment variables		61
- Referencing variables		63
- Quoting			64
- Tilde expansion			66
- Customizing your Login		67
- The Online Manual		68
- Apropos			69
- Who				70
- W				71
- Finger			72
- Regular Expressions		73
- Single Character REs		74
- Character Class REs		75
- More Complex REs		76
- RE Examples			77
- grep				78

- _Subject__	__	_                      _Page #_
- egrep				79
- 	An egrep Example		80
- Mail				81
- 	Reading Mail		82
- 	Sending Mail		83
- Foreground vs Background		85
- Processes			86
- Kill				87
- Job Control			88
- 	Job Control Example		89
- Shell Scripts			90
- Sample Shell Script		91
- Control Flow in Scripts		92
- Parameters			93
- Important Directories		94
- Manipulating Files and Inodes		95
- Device Files			98
- Disk Devices			100
- Terminal Devices			101
- The NULL Device		102
- Yet More Shells			103
- Shell Metacharacters		104
- Table of Metacharacters		105
- Quoting			107
- Continuations and Comments		108
- Creating New Commands		109
- PATH Environment Variable		111

## Table of Contents

- _Subject__	__	_                        _Page #_
- Exercise 1. Finding shell scripts		112
- Arguments and Parameters		113
- Example: 411, directory information	114
- Program Output as Arguments		115
- Shell Variables			116
- Exporting Shell Variables		117
- Modifying Shell Variables
- 	The . command		118
- Here Documents 			119
- Looping in Shell Programs		120
- Putting it all together		122
- Filters			123
- Other Filters			124
- sort				125
- Stream Editor, sed		126
- Sample sed Commands		127
- Summary of sed Commands		128
- Exercise: sed			129
- awk - 			130
- 	pattern scanning and processing language
- awk Arrays			132
- sed and awk			133
- Bourne Shell Programming		134
- Shell Built-In Variables		135
- The set command			136

- _Subject__	__	_                        _Page #_
- case Statements			137
- Shell Pattern Matching Rules		138
- Example case Statements		139
- Control flow: which command?		140
- which command? - PATH elements		141
- Conditional execution: if		142
- Testing Things			143
- Which Command?  - which		145
- for loops revisited		146
- while and until loops		147
- Example: while and until		148
- Exercise: looping			149
- Evaluation of shell variables		150
- Accepting User Input: read		151
- Traps: catching interrupts		152
- Shell Signal Numbers		153
- Aliases			154
- Shell Functions			155
- Example Shell Function		156
- Style				158

## What is UNIX?

- A trademark for any of several computer operating systems developed at AT&T Bell Labs.
- A computer operating system or interface that bears a significant resemblance to UNIX.
- Associated with UNIX.  “The UNIX Shell.”

## UNIX History, Part 1

- 1969	Version 1.  Written by Dennis Ritchie and Ken Thompson for the DEC PDP-7.
- 1973	Version 4.  This was the first version written in C.  The translation into C made UNIX portable, and was fundamental to its eventual success.
- 1975	Version 6.  This was the first version widely available outside AT&T, and the first version that was ported to several architectures.
- 1979	Version 7.  The common ancestor of most commercial UNIX versions, version 7 was ported widely and documented in the famous blue and green books.  These were the first generally available references to UNIX.

## UNIX History, Part 2

- Early 1980s
-            University of California at Berkeley was contracted by DARPA to add virtual memory support to UNIX for use on DEC VAX computers.   Berkeley was later contracted to add Internet style networking to UNIX.  “Berkeley UNIX”, aka BSD, became very popular with academia and began to diverge from AT&T UNIX.
- 1983	System V.  AT&T released this version with much fanfare, declaring it to be* the* UNIX standard.  Many commercial versions were based on it.  The Great BSD vs AT&T War had begun.

## UNIX History, Part 3

- 1985	BSD versions 4.2 and 4.3 were used as the basis for many commercial UNIX releases, including SunOS and Ultrix.  Many AT&T based releases include  “Berkeley enhancements”.
- 1988	Sun, AT&T and Microsoft merged their versions of UNIX into System V, Release 4 (SVR4).  The BSD vs AT&T War ended with no winner, because...
- 1988	Several companies, unhappy with SVR4, form the Open Software Foundation.  OSF creates OSF/1, a UNIX clone based on Mach from Carnegie Mellon University.  The Great SVR4 vs OSF/1 War had begun...

## UNIX History, Part 4

- 1992    Unix System Laboratories bought by Novell, ending 23 years of control by AT&T over UNIX.  Novell pledges to make UNIX a major desktop platform, fully integrated with Netware.  Move is widely viewed as a response to Microsoft’s upcoming Windows NT.
- 1993    UNIX International and the OSF kiss and make up, with various members of each forming COSE, the Common Open Software Environment.   Move is widely viewed as a response to Microsoft’s upcoming Windows NT.

## Vendors and Versions

- IBM	AIX (Sys V)
- DEC	Ultrix (BSD)
- Apple	A/UX (Sys V)
- HP/Apollo	HP/UX (Sys V, lots of BSD)
- CMU	Mach (kitchen sink)

- AT&T	System V R2, R3, R4
- Sun**	**SunOS (BSD), now Solaris (SVR4)
- Microsoft	Xenix (Sys V)
- Silicon Graphics	Irix (Sys V)

**Unix International:**

**Open Software Foundation:**

## What makes it UNIX?

- Multitasking
- Multiuser
- Networked
- Portable

## Multitasking

- Multitasking is the ability of a computer system to execute more than one program at a time.   UNIX has always been a multitasking system.
- Modern PC operating systems like Microsoft Windows 3.0 and Mac System 7 feature *co-operative multitasking*.  Under co-operative multitasking, an application must voluntarily give up the system to another task.
- UNIX, and PC operating systems such as OS/2 2.0 and Windows NT, use *pre-emptive multitasking*, under which the system can grab control from one application and give it to another.

## Multiuser

- A multiuser system is one that can be used by more than one person at a time.  Multiuser systems are inherently multitasking.
- A multiuser system requires some method of determining the identity of any given user.  This *login name* is used to determine ownership of files and to control access to data and programs.
- LAN operating systems such as Novell and LAN Manager incorporate many of the ideas of multiuser systems.  Microsoft’s upcoming Windows NT is  multi-user, with restrictions.

## NetworkedTCP/IP

- Networking in UNIX is based almost entirely on the Berkeley TCP/IP implementation.
- The cheap availability of the Berkeley networking code led to its incorporation into many commercial versions of UNIX and to the standardization of the *sockets* interface.
- Every important networking standard is supported under UNIX:  Ethernet/802.3, TCP/IP, DECnet, Novell, Token Ring, XNS, etc.

## Networkeduucp

- The uucp program copies files from one UNIX computer to another over a serial port.  This basic transport layer provided the basis of the earliest networked UNIX mail systems and later the vast  “netnews” network.
- The uucp network that lead to USENET began at Duke University and grew rapidly.  This user supported, phone based network carries mail and the netnews distributed bulletin board, the largest computer conferencing system in the world.
- Until SVR4, uucp was the only networking capability provided by AT&T’s versions of UNIX.

## Portable

- UNIX runs on systems ranging from 16-bit embedded microcontrollers up through the largest mainframes and supercomputers.
- The IEEE POSIX specification defines the of the basic features of UNIX.  The POSIX standard further enhances the portability of UNIX applications.
- This portability is possible because UNIX is written in a high level language, C, instead of assembly.

## Starting a UNIX Session

- UNIX users are given a *login name *and a *password*.
- The login name identifies you to the system
- The password assures the system that you are who you claim to be.
- Your initial password will be assigned by the system administrator but you can change it at any time.

## Logging into UNIX

- Prior to login, you will be presented with the login prompt, which typically contains the system name.
- 	nssdcs login:
- At this point, enter your login name.
- 	nssdcs login: *williams*
- 	Password:
- The system will prompt for a password.  The characters of the password will not echo as you type them.

## Logging into UNIX, Cont'd.

- After a successful login, you will be shown a greeting and possibly a “message of the day”.
- A message may inform you that "You have mail."
- Finally, you will get a *shell prompt*, which defaults to $ or %, depending on your shell.
- 	%

## The Shell

- The *shell*  is the UNIX command interpreter.  It serves the same basic function as COMMAND.COM under DOS or DCL under VAX/VMS.
- All of the programs you run will be started by issuing commands to the shell.
- There are several shells in common use:
- sh		The Bourne shell
- csh		The C shell
- ksh		The Korn shell
- Under System V Release 4 ksh is the default shell.

## Shell Command Syntax

- Simple commands are run just by typing their name.
- 	% 		*who*
- 	kirk     		console 	Oct  6  9:22
- 	spock    	ttya    		Oct  6  8:07
- 	scott    		ttyp3   		Oct  5 22:20 	(eng.ncc1701.ufp)
- 	mccoy    	ttyp4   		Oct  6  8:03 		(med.ncc1701.ufp)
- 	williams 	ttyp8   		Oct  6 10:16 	(eng.ncc1701.ufp)
- Many commands take *arguments*, often one or more filenames.
- 	% *cd myprograms*
- 	% *sort mydata1 mydata2*

## Options vs Arguments

- In addition to *arguments*, most commands have one or more *options*.
- Arguments usually specify the objects on which the command is to operate
- Options affect the nature of the operation and usually begin with a dash (-).
- The command below includes both options and arguments.
- 	% *sort -n -r datafile1 datafile2*
- Most commands allow options to be either grouped or separated.
- 	% *sort -rn datafile*

## The Standard Output

- Programs that produce output typically write it to the
*standard output*.  By default, the standard output is the terminal screen.
- 	% *sort animals*
- 	aardvark
- 	cat
- 	gazelle
- 	tiger
- The standard output can be made to go to into a file by
*redirecting* it with >
- 	% *sort animals > sorted_animals*

## The Standard Input

- Similarly, most programs read from the *standard input*, unless otherwise instructed.  The default standard input is the terminal keyboard.
- 	% *sort*
*	**gazelle*
*	**aardvark*
*	**cat*
*	**tiger*
*	**^D*
- 	aardvark
- 	cat
- 	gazelle
- 	tiger
- The standard input can also be redirected, using <
- 	% *sort < animals*
- 	aardvark
- 	cat
- 	gazelle
- 	tiger

**Control D marks the end of input.**

## Appending

- When redirecting the standard output to a file, if the file already exists, the new contents will replace the old.  It is also possible to append the new contents to the old.  This is done with the symbol >>
- 	% *cat > party_guests*
- 	*samir*
*	**george*
*	**anne*
*	**^D*
- 	%* cat >> party_guests*
*	**grace*
*	**rick*
*	**^D*
- 	%

## Standard Error

- In addition to the standard input and standard output, there is also a *standard error output*
- Used for error messages.
- Redirection of standard output does not affect standard error.
- 	% *sort aminals > sorted_animals*
*	*sort: aminals: file not found.
- The standard error may also be redirected or combined with the standard output.
- Under the Korn or Bourne shells, use 2>.
- To combine standard error with standard output, use 2>&1.
- Under the C Shell, use >&, which redirects both stdout and stderr.
- 	% *sort aminals 2>&1 > sorted_animals*

## Pipes and Filters

- It is possible to connect the standard output of one command to the standard input of another.  This is called a *pipe*.
- 	% *who | sort*
- 	kirk     		console 	Oct  6  9:22
- 	mccoy    	ttyp4   		Oct  6  8:03 		(med.ncc1701.ufp)
- 	scott    		ttyp3   		Oct  5 22:20 	(eng.ncc1701.ufp)
- 	spock    	ttya    		Oct  6  8:07
- 	williams 	ttyp8   		Oct  6 10:16 	(eng.ncc1701.ufp)
- The concepts of standard input, standard output, and the pipe were fundamental to creating the “tool building” philosophy that is central to UNIX.

## The UNIX File System

- UNIX files are organized into a tree-structured hierarchy.
- Each user is given a spot in the tree that is his or her default directory at login time.  This is the user's *home directory*.
- Users may create any arrangment of subdirectories they like under their home directory.

## UNIX File Names

**UNIX ****file names are versatile and nearly unrestricted.**
- They may contain almost any character
- File names are case sensitive!  **FooBar** and **foobar** are different files!
- They may be of almost any length (up to 255 characters on most systems).
- '.' is *not* a special character in UNIX.  File names such as **this.is.a.very.peculiar.file.name** are permitted and not uncommon.

## The UNIX File System Hierarchy

- UNIX file name components are separated by slash characters (/).
- A typical UNIX system has a file tree that looks like the following.
- / (root)
- 	bin/  Some programs live here
- 	usr/  System files for users are here
- 		bin/    	Lots of programs live here
- 		lib/    	C libraries, special programs
- 		local/  	Locally developed packages
- 		etc/    	System administration programs
- 	etc/   System configuration files
- 	home/  User's home directories (sometimes /user or /u)
- 		williams/
- 		kirk/
- 		spock/
- 		mccoy/
- 		scotty/

## File Name Expansion(Wildcards)

- The shell allows file names to be specified using a pattern.  The shell expands the pattern into the actual file names.  The process of expanding a file name pattern is called *file name expansion *(or, by old-timers, *globbing*).
- The special characters used to construct file name patterns are ?, *, and [].

## Wildcard Characters

- The ? character matches any single character.
- % *ls foo.?*
- foo.h
- foo.o
- foo.c
- The ? character can be used any where in the file name pattern and always matches exactly one character.
- % *ls ???.c*
- foo.c
- bar.c
- zap.c

## Wildcard Characters,Cont'd.

- The * character matches any group of zero or more characters.
- % *ls *.c*
- main.c
- io.c
- edit.c
- Unlike DOS's filename wildcards, the * character can be used more than once in a pattern, and can be the first character.
- %* ls *cat**
- catalog
- concat.c
- scatter_plots

## Wildcard Characters,Cont'd.

- The characters [] are used to surround *character classes*.  Each character class matches exactly one character.  Thus,
- 	% *ls [fbm]oo*
- will match *foo, boo*, and *moo*, but not zoo.  A range of characters can be specified by separating the first and last character of the range with a hyphen.
- 	% *ls [A-Z]**
- This pattern matches all files that begin with an upper case letter.  Character classes may contain ‘*-*’, but not as the first character.

## Common UNIX Commands

**Below are some common ****UNIX ****commands.  Each command will be explained in detail later.**
- ls	List the contents of a directory
- cd	Change to another directory
- echo	Print text on screen
- more	View a file
- cat	Concatenate and print files
- mv	Rename or move a file
- cp	Copy a file
- mkdir	Make a new directory
- rmdir	Remove an empty directory

## lsList Contents of a Directory

- With no arguments, lists the names of all files in the current directory.  The list will be sorted down the columns by default.
-    bin		mbox		projects
-    calendar	mystuff	src
- ls has a huge number of options.  A commonly used option is  -l, which produces a long listing.
-    % *ls -l*
-    -rw-r--r-- 1 		williams   	261 	Oct  3 08:28 	calendar
-    -rw-rw-r-- 1 	williams 	17264 	Oct  6 13:17 	mbox
- This listing gives the permission bits, the number of links, the file owner's name, the size of the file in bytes, the date and time it was last modified, and the file's name.

## ls - More Options

- File names that begin with *a* . are normally hidden and most programs ignore them.  (They are *not* matched by ‘*’ or ‘?’ in file name patterns.)  The *-a *option to *ls* will include these files in the output:
- % *ls -a*
- .   .cshrc		.profile	calendar
- ..  .login		bin		mbox
- The *-F *option will print a character at the end of each file which identifies the file's type.  A directory is suffixed with /, an executable with *, a symbolic link with @, and a plain file is left alone.
- % *ls -F *
- bin/		mbox	myprog*
- calendar	mystuff/	myprog.c

## cd and pwdChange to Another Directory

- A *cd* by itself will take you to your home directory.
- Under DOS, a plain *cd* prints your current directory.
- Under UNIX, the *pwd* (print working directory) command will print the current directory.
- % *cd*
- % *pwd*
- /home/staff/williams
- Go to the directory src, in the current directory.
- % *cd src*
- Go to the directory immediately above this one.
- % *cd ..**	*

## mkdirMake a New Directory

*mkdir* is used to create a new directory.  The example below will make directories *foo, bar*, and *baz*, located in the current directory.  The current directory becomes their *parent*  directory.
- % *mkdir foo bar baz*
- New directories can be made anywhere you have the necessary permissions (i.e., you must have "write permission" on the parent directory).
- % *mkdir /tmp/jim*

## rmdirRemove a Directory

*rmdir *will remove an empty directory.  Only empty directories may be removed (but see *rm -r*, later).
- % *rmdir /tmp/jim tmp*
- To remove a directory, it must be empty and you must have write permission on the parent.  Some systems put further restrictions on file and directory removal.

## echoPrint Text on Screen

- The *echo* command causes its arguments to be printed on the screen.
- % *echo foo bar baz*
- foo bar baz
- The *-n *option supresses the final newline, which is useful for prompts in shell scripts.
- % *echo -n "Enter name: "*
- Enter name: %
- The System V R4 echo also supports several C-like escapes, which permit certain special effects.  Many UNIX purists hate this “feature”.

## moreView a Text File

- The *more* command is the most common program used for file viewing.
- % *more stuff.text*
*more* will display one page at a time, waiting for the user to hit a key before going on to the next page.  DOS's crippled more is based on this program.
- System V based systems have *pg* (for “page”), rather than *more*.  *pg* is very primitive compared to more.  A much better pager is the freely available less program. less is rather more than more, and quite a bit more than *pg*.  This can be confusing.

## catConcatenate and Print Files

*cat* is used to combine, or concatenate, files, and send them to the standard output.
- no pauses occur between screenfuls of text.
- mostly used  to combine several files into one
- % *cat foo bar > foobar*
- Some versions of *cat* have options for printing tabs and newlines as visible characters and for other special effects.  Some UNIX purists hate these, usually the same ones who hate the System VR4 echo escapes.

## catEntering Short Files

*cat* can also be used to enter a small amount of text into a file.  With no arguments, *cat* will read from the standard input.
- % *cat > shopping_list*
*milk*
*orange juice*
*apples*
*cereal*
*^D*
- %

## mvMove or Rename Files

- To rename a file, one moves it into a new name with *mv*.
- % *mv foo bar*
- Unlike DOS's* ren *command, the destination can be anywhere.
- % *mv shopping_list mystuff/shopping_list*
- If the destination is a directory that the user can write in,
- then a file of the same name as the original is created.
- % *mv shopping_list mystuff*
- % *ls mystuff*
- birthday_list	phonebook	shopping_list

## mvMove or Rename Directories

*mv* can also rename or move directories.
- % *mv prog1 oldstuff/prog1*
- If the destination already exists and is a directory, then *mv* will make the source a sub-directory of the destination.
- % *mv prog1 oldstuff*

## mvOptions

- If you *mv* a file on top of an already existing file, the old file is deleted, without warning.
- % *ls*
- bar foo
- % *mv foo bar*
- % *ls*
- bar
- The -i option will cause *mv* to ask permission before removing a file of the same name as the destination.
- % *mv -i foo bar*
- remove bar? *y*
- %

**Any response that begins with y counts as yes.**

## rmRemove Files

- Use *rm* to remove one or more files.
- % *rm a b c*
- Filename expansion is both useful and dangerous with rm!
- % *rm *.o*
- % *rm * .o*
- rm: .o: file not found
- The -i option can be used to prevent such tragedies.  This
- option will cause rm to prompt for confirmation before it removes each file.

**YIKES!**

## rmRecursive Removal

*rm* also has the *-r *option, which causes *rm* to recursively remove all files and subdirectories, including hidden files.
- 	% *rm -r oldstuff*
- Obviously, the combination of the *-r *option and filename wildcards is *very dangerous* and should be used with great caution.

## cpCopying Files

*cp*  is used to make a copy of a file.
- %* cp foo bar **	**	*
- Multiple files can be copied into a subdirectory.
- %* cp foo.c bar.c baz.c backups*
- The above command copies the three *.c *files into the directory *backups*.  The new files will have the same names as the originals.  If *backups* doesn't exist, *cp* will complain.

## cpOptions

*cp* can also act recursively, to copy an entire tree.
- 	% *cp -R dir1 dir2*
- Like *mv* and *rm*, *cp* supports the  *-i *option.
- The *-p *option to *cp* will set the modification time of the copy to be the same as that of the original.  By default, the modification time of the copy will be the current time.  *-p *also tries to set the permission bits on the copy to be the same as on the original.

## File Ownership

- All files under UNIX have an *owner* and a *group*.  The owner and group for a file are found in a long ls listing.
- % ls -lg
- total 47
- drwxrwsr-x 	3 williams staff    	512 	Oct  6 13:41 	./
- drwxrwsr-x  	4 williams staff    	512 	Jul 17 09:46 	../
- drwxrwsr-x 	2 williams staff    	512 	Oct  6 11:02 	bin
- -rw-rw-r--  	1 williams staff   	1194 	Sep  9 13:27 	calendar
- -rw-rw-r--  	1 williams staff  	17264 	Oct  6 13:17 	mbox
- drwxrwxr-x  	1 williams staff    	161 	Oct  5 16:18 	mystuff
- The files above are owned by williams in the group staff.
- A file is owned by the user who creates it.
- The initial group of a file depends on several things.
- File ownership can be changed with the chown command.
- File group can be changed with with chgrp command.

## File Access

- % ls -l
- total 47
- drwxrwsr-x  	3 williams staff    512 	Oct  6 13:41 	./
- drwxrwsr-x  	4 williams staff    512 	Jul 17 09:46 	../
- drwxr-sr-x  	2 williams staff    512 	Oct  6 11:02 	bin
- -rw-rw-r--  	1 williams staff   1194 	Sep  9 13:27 	calendar
- -rw-------  	1 williams staff  17264 	Oct  6 13:17 	mbox
- drwxrwxr-x  	1 williams staff    161 	Oct  5 16:18 	mystuff
- In a long listing the first group of characters gives each file's *permission bits,* which define the access rights to the file.
- The first character gives the file's type, the next nine give the file’s access permissions for the owner, the group, and others.
- - is used for a plain file, d is used for a directory, l is used for a symbolic link.
- r, indicates read permission, w indicates write permission, x and s indicate execute permission.

## chmod

- The *chmod* command is used to change the permission bits (the mode) of a file.  There are two different styles of argument to chmod.  The first style, used by old-timers and programmers, uses octal numbers to change the mode of a file.
- % *chmod 644 myfile*
- This sets myfile to have permissions -rw-r--r--.  The other option syntax uses symbolic values and is a bit more user friendly.
- % *chmod a=r myfile*		everyone gets just read permission
- % *chmod ug+w myfile**	*owner (user) and group get write permission
- % *chmod go-x myprog**	*group and others have no execute permission

## GroupsThe Old Way

- At any given time, a user is “in” exactly one group.
- New files and directories are given the group ID of the user when the user creates the file.
- The *newgroup* command allows the user to switch amongst any of the groups for which the user is authorized.
- Doesn’t work well for users who work on many projects.

## GroupsThe New Way

- Starting with about BSD 4.1, a new method of setting the group ID was introduced which facilitated working on many projects at once.
- New files and directories are given the group ID of the directory in which they are created.
- Users are always “in” all the groups they are authorized for so *newgroup* command is not needed.
- Group ID is a property of location, not the creator.

## GroupsEvery Which Way

- When the BSD and System V variants of UNIX were merged, some compromise on groups had to be made.  The solution allows both sorts of behavior, but is a little complex.
- Any directory with the set group id* *bit not set uses Old Way semantics.  Files created there will get the group id  of the creator.
- Any directory with the set group id bit set uses New Way semantics.  Files created there will have the group id of the parent directory.
- In both cases, a new directory has its set group id bit set the same as the parent directory.

## Shell Variables

- The shell maintains certain information in its own variables.  Shell variables affect how the shell searches for commands, set the shell's prompt, and otherwise customize its behavior.  Under *sh* and *ksh*, shell variables are set by following them with an equal sign (=) and the value to be set.
- 	% *prompt=giss:*
- 	giss:
- Note that NO SPACE is allowed on either side of the =.  To see what variables are set, use the
*set* command with no arguments.
- 	% set

## Important shell variables

- The shell sets up some variables automatically when you log in.  You can customize these values to suit personal preferences or for special situations.  The variables below are among the more important.
- home -	The location of your home directory
- path -	A list of directories to search when trying
- 		to  find a command
- user -	Your login name
- prompt -	The string to print when prompting for the
- 		next command

## Environment variables

- Shell variables affect only the shell and how it interprets your commands.  Programs you run can not access shell variables.  There is a separate set of variables, called the *environment*, that any program can access.  All shells provide commands for manipulating these *environment variables*.
- To see all currently set environment variables, use printenv.
- 	% *printenv*
- 	HOME=/home/systems/williams
- 	PATH=.:/bin:/usr/bin:/usr/local/bin

## Environment variables,Cont'd.

- To change the value of an environment variable, or to create a new one, use setenv.
- 	% *setenv TERM vt100*
- Some common environment variables follow.
*HOME*		- your home directory
*TERM*		- type of terminal you are on
*PATH*		- search path for commands
*LOGNAME*	- your login name
*VISUAL*		- screen editor to use
*EDITOR*		- line editor to use
*PAGER**	**	*- program to use for displaying text files
*PRINTER*		- default printer to use

## Referencing variables

- Both shell and environment variables are referenced by preceding the name with a $.
- % *echo your terminal type is $TERM*
- your terminal type is vt220
- % *cd $home/mystuff*

## Quoting

- The shell interprets some characters specially.  To include these characters as arguments or options to a command, they must be *quoted*.  There are several quoting mechanisms, each of which serves a distinct purpose.  The simplest quoting method is to enclose the argument in single quote marks (').
- 	% echo 'this is a single argument'
- 	% grep '*foo*' list
- Filename expansion characters such as *, ?, [ and ] lose their special meaning inside single quotes.

## Quoting, Cont'd.

- Inside of single quote marks ('), shell and environment variables are not expanded.
- % *echo 'your home directory is $HOME'*
- your home directory is $HOME
- If double quotes (") are used, then shell and environment variables are expanded.
- % *echo "your home directory is $HOME"*
- your home directory is /home/williams

## Tilde expansion

- In the Korn or C shells, the tilde character (~) can be used as a convenient short hand for home directories.  When a tilde is at the beginning of a word, and the next character is a /, the tilde is replaced by the contents of $home, your home directory.  The following command sets the current directory to *$home/mystuff*.
- % *cd ~/mystuff*
- If the tilde is followed by a user name, it is replaced by that user's home directory.  The command below copies the file *engine_specs *from user scotty's home directory and puts the copy in my directory mystuff.
- % *cp ~scotty/engine_specs mystuff*

## Customizing your Login

- When a Bourne or Korn shells start up, it looks to see if a file named *.profile *exists in the user's home directory.  If so, the contents of that file are executed as if typed into the user's terminal before control is given to the user.  This allows the user to put customizing command in the *.profile *file.  This is much like the DOS *autoexec.bat* file.
- The C shell also allows customization, but since it has a different syntax for many functions, it uses the files *.cshrc *and *.login *for customization.

## The Online Manual

- UNIX provides an on-line version of the User's Manual which is accessed via the man command.  If you know the name of a command, the manual page for that command may be displayed with the man command shown below.
- 	%* man grep*
- man can also be used to look up information about library routines.
- 	% *man strcpy*
- This command will return information on the C library string copy function, *strcpy*.

## Apropos

- If you are unsure of a command's name, but know what it does, you can use the *-k *option to search for the right entry.
- % *man **	**	**-k password*
- getpass (3V)	- read a password
- getpwent (3V)	- get password file entry
- passwd (5)		- password file
- passwd (1)		- change password
- putpwent (3)	- write password file entry
- On many systems, the command apropos is the same as  *man -k*, but since no one can spell apropos without looking it up, this isn't of much help.

## Who

- To find out who is on the system, use who.
- % *who*
- kirk     		console 	Oct 25 10:00
- williams 	ttya    		Oct 25 08:35
- spock    	ttyp1   		Oct 25 09:31 	(sci.ncc1701.ufp)
- mccoy    	ttyp2   		Oct 25 10:12 	(med.ncc1701.ufp)
- scott    		ttyp4   		Oct 23 10:01 	(eng.ncc1701.ufp)

## W

- Some systems also have the  w command, which shows what users are doing.
- % w
- 1:40pm  up 9 days,  3:12,  5 users,  load average: 0.07, 0.03, 0.00
- User     	tty       		login@			idle   	JCPU   	PCPU  	what
- williams 	ttyp0     	8:35am		19  	18:31      	1  	-csh
- kirk     		ttyp1     	9:31am		2     	20         		vi cptns_log
- spock    	ttyp2    	10:12am		4     	15         		emacs pi.c
- mccoy    	ttyp4    	Wed10am	1:12     	38      	1  	-ksh
- scotty   	ttyp7    	10:02am			9:33      	5  	mail

## Finger

- If you can't recall a user's login name, you can use finger to help find it.
- % *finger bones*
- Login name: mccoy	    In real life: Leonard "Bones" McCoy
- Directory: /home/sickbay/mccoy  	Shell: /bin/ksh
- On since Oct 25 08:35:30 on ttyp0 from med.ncc1701.ufp
- 20 minutes Idle Time
- No unread mail
- Project:  To keep the crew of the Enterprise in perfect health.
- Plan:
- I'm a doctor, not a bureaucrat!
- Cabin Phone:	1 301 555-1131
- Lab Phone:		1 301 555-7253

## Regular Expressions

- Several UNIX commands make use of the concept of a *regular expression*. Regular expressions are similar to filename wildcards, but much more powerful.  All of the standard editors use regular expressions, as well as commands such as *grep, awk*, and *sed*.  A solid understanding of regular expressions is vital to making full use of UNIX.

## Single Character REs

- A single character matches itself.
- 	a
- The character . matches any single character.
- 	.

## Character Class REs

- A set of characters in a brackets ([]) matches any one of those characters.
- 	*[abcd] *- matches a, b, c, or d
- Ranges are specified by using - to separate the first and last character in the range.
- 	*[a-z] *- matches any lowercase letter
- If the first character is ^, then the range is complemented.
- 	*[^1234567890] *- matches any character that is *not **	**	**	**	**	*a digit

## More Complex REs

- For any regular expressions *re, re1*, and *re2*, the following are valid combinations.
- re1re2		- matches a match for re1, followed by a match for re2
- re*		- matches 0 or more occurances of re
- re{m-n}	- a range of repetitions, at least m, but no more then n
- ^re		- re must be at the beginning of the line
- re$		- re must be at the end of the line
- \(re\)		- label
- \n		- back reference to label n, in the range 1-9
- A regular expression always matches the longest string possible.

## RE Examples

- [A-Za-z_][A-Za-z_0-9]*
- Matches any letter or underscore, followed by any number of
- letters, digits or underscores.
- [0-9][0-9]*[A-Za-z]*[0-9][0-9]*
- Matches at least one digit, followed by any number of letters
- (including none), followed by another sequence of digits.
- \([0-9][0-9]*\)[A-Za-z]*\1
- Matches at least one digit, followed by any number of letters,
- followed by *exactly the same sequence *of digits.

## grep

- The *grep* command is used to search one or more files for lines matching a regular expression.  For a simple string, the command would be a follows.
- % *grep Galileo data.1 data.2 data.3*
- Regular expressions that contain special characters must be quoted, so that the shell doesn't give the characters its own special meanings.
- %* grep '[aeiou].*[^aeiou]' wordlist*
- The name grep comes from the equivalent editor command, *g/RE/p*, which means to globally search for the given RE and print each matching line.

## egrep

- The *egrep* command supports extensions to the regular expression syntax.
- re+	- one or more repetitions
- re?	- zero or one repetitions
-        - alternation
- The *egrep* command does  not allow back references via \n.  Parentheses may be used for grouping.
- % *egrep 'Galileo|Viking' data.1 data.2*

## An egrep Example

- To practice an extended pattern that contains a few of the
- pattern-matching characters +, ?, I, (, and ), enter:
*egrep “\( *([a-xA-X]*I [0-9]*)” mygrepfile.txt*
- This displays lines that contain letters in parentheses or digits
- in parentheses, but not parenthisized letter - digit combinations.  It matches t and 873902, but not beta18b.
- Note that the reverse slash matches parentheses but without it both parentheses are used as a part of an expression (opposite to grep).

## Mail

- There are several popular mail reading programs available under UNIX.  The most broadly available program is the Berkeley* mail *program.  To read your mail, you simply run *mail* with no arguments (on some versions of System V, this is called Mail, or mailx).
- % *mail*
- Mail version SMI 4.0 Mon Apr 24 17:36:21 EDT 1989 Type ? for help
- "/usr/spool/mail/williams":3 messages
- >N  1 kirk       Fri Jul 14 12:01 21/455 Orders for wil
- N  2 spock      Sat Jul 15  8:45  4/78  With regard to
- N  3 scotty     Sat Jul 15 15:32 23/626 New engine spe
- &

## Reading Mail

- The following commands can be given at the mail prompt (&).
- # - read the message given by the number
- d - delete one or more messages
- r - reply to just the sender of a message
- R - reply to all recipients of a message
- m - send mail
- s - save a message in a file
- c - copy a message to a file
- q - quit from mail, with unread mail staying in your system mailbox and undeleted mail going to the file mbox
- x - exit from mail as though you had done nothing

## Sending Mail

- To send mail, run the *mail* command with the name of the recipients as arguments.
- % *mail kirk spock*
- Subject:* Request for leave*
*I would like to request shore leave the next time the Enterprise reaches a class M planet or a starbase.*
*Thanks,*
*Lt. Cmdr. Williams*
*^D*
- cc:* scotty*
- %

## Sending Mail

- When sending mail, several *tilde escapes *are available for special purposes.
- ~m # - include the given message number in the reply
- ~r filename - read the named file into the message
- ~v - invoke the editor given in $VISUAL on the message
- ~p - print out the message as entered so far
- ~h - print out the message headers and allow corrections

## Foreground vsBackground

- Normally, UNIX programs are run in the foreground, which means that the user must wait for one command to finish before entering another.  If you wish to run a command that will take a long time,  you can put the command in the background, which allows you to get on with other work.
- % *sort -o output very_long_file*
- % *edit report*
- To put a command in background, end it with an &. The *process ID* of the command will be printed.
- %* sort -o output very_long_file &*
- 10324
- %* edit report*

## Processes

- To see what processes you have running use the *ps* command.
- % *sort -o output very_long_file &*
- 6542
- % *ps*
-  PID TT STAT   TIME COMMAND
- 6542 p0 R      0:00 sort very_long_file
- 6543 p0 R      0:00 ps
*ps* has many options, which vary from system to system.  Consult your local man page for details.

## kill

- Sometimes it is necessary to terminate a process that is hung, or running amok, or otherwise has become undesirable.  The *kill* command is provided for this.
- % *kill 1283*
- The above command will send the *KILL signal *to process 1283.  Other signals* *are possible.  They
- are given as options to *kill*.
- % *kill -TERM 1283*
- The  TERM signal allows the application to clean up before quitting.  The default KILL signal halts an application without notice.

## Job Control

- Under traditional UNIX, once a command has been started in foreground or background, that's where it stays until completion.  Berkeley UNIX introduced the notion of job control, which allows processes to be moved from foreground to background while they are running.  Job control is available in the Berkeley C shell and the Korn shell.
- A job that is currently running in foreground can be *stopped*  by typing ^Z.  Once a job is stopped, it can be restarted in either the foreground or background with the *fg* or *bg* commands, respectively.  The *jobs* command displays the status of all current processes.

## Job Control Example

- % *sort bigfile.1 > sorted.1 &*
*[1] 18828*
- %* sort bigfile.2 > sorted.2*
*^Z*
- %* jobs*
- [2]   + Stopped sort bigfile.2 > sorted.2
- [1]   - Running sort bigfile.1 > sorted.1
- % *bg*
- [2]   sort -o bigfile.2 > sorted.2
- % *jobs*
- [1]     Running sort bigfile.2 > sorted.2
- [2]   + Running sort bigfile.1 > sorted.1
- % *fg %1*
- sort bigfile.1 > sorted.1
- % *kill %2*
- [2]   Terminated   sort bigfile.2 > sorted.2

## Shell Scripts

- The UNIX shells all allow for the creation and execution of *shell scripts*, which are simply files that contain lists of commands for the shell to run.  Unlike *.BAT *files  under DOS, or *.COM *files under VMS, there is no special extension required on UNIX shell script files.  It is, however, necessary to set the execute permission bit on a shell script file, or the shell will not execute the script.

## Sample Shell Script

- All shell scripts should start with the characters #!, followed by the name of the shell for which the script was written.  Since the different shells have different syntaxes, this prevents errors caused when the wrong shell tries to execute a given script.
- #!/bin/sh
- #
- # This is a korn shell script.
- # A pound sign (#) begins a comment, which
- # extends to the end of the line.
- echo -n "Today is "
- date
- echo "The users currently logged in are:"
- users

## Control Flow in Scripts

- Shell scripts often make use of control flow statements such as those found in high level languages.
- #!/bin/sh
- # This script removes .o files that are
- # older than the corresponding .c file.
- for cf in *.c
- do
- 	of=${cf%.c}.o
- 	if [ -e $of -a $of -ot $cf ]
- 	then
- 		echo "Removing " $of
- 		rm $of
- 	fi
- done

## Parameters

- Shell scripts can take arguments and options just like programs.  These are called the *positional parameters *and  are refered to in the script by the variable names $1 through $9.  The number of positional parameters passed to a script is given by $#.  Parameter $0 is the name of the script.  The first argument is in $1. Under the Bourne shell, parameters beyond $9 must be accessed via the *shift* command, which shifts arguments left by one, starting with $1.  Under the Korn shell, arguments beyond $9 require braces, for example, ${16}.

## Important Directories

- /			root of the file system
- /bin			essential programs in executable form
- /dev			device files
- /etc			essential and miscellaneous system configuration files
- /lib			essential libraries
- /tmp			temporary files; writable by all users
- /usr			user file system
- /usr/adm		system administration; accounting info
- /usr/bin		user binaries; cut, tar, troff, etc.
- /usr/include		header files for C programs
- /usr/lib		libraries for C, Fortran, other system services
- /usr/man		on-line manual pages
- /usr/man/man1	manual pages for section 1
- /usr/spool		working directories for communications programs
- /usr/spool/lpd		line printer spool
- /usr/spool/mail	electronic mail boxes
- /usr/class		various places where user home directories reside
- /usr/users/class
- /home/class

## Manipulating Files and Inodes

**ln(1)makes a new link to an existing file**
- Using the *link*(2) system call
**The same file will then have *****two names***
- $ *ln junk linktojunk*		# Create a new link
- $ *ls -li *
- 14209 -r--r--r-- 2 leb users    		29 Jul 28 15:20 junk
- 14209 -r--r--r-- 2 leb users    		29 Jul 28 15:20 linktojunk
- $ *chmod u+w linktojunk*		# Change permissions
- $ *ls -li*
- 14209 -rw-r--r-- 2 leb users    		29 Jul 28 15:20 junk
- 14209 -rw-r--r-- 2 leb users   		29 Jul 28 15:20 linktojunk
- $ *rm linktojunk*			# Remove the link
- 14209 -rw-r--r-- 1 leb users   		 29 Jul 28 15:20 junk

## Manipulating Files and Inodes(continued)

*rm(1) *breaks links (using the *unlink(2) *system call). When the link count is zero, the file contents are released.
- _Once the file is gone, it is gone forever.  BE CAREFUL!_
*cp (1) *makes a real copy: name, contents, and inode
- $ *cp junk copyofjunk*		# Create a new copy
- $ *ls -li *
- 14211 -rw-r--r-- 1 leb users    		29 Jul 28 15:28 copyofjunk
- 14209 -rw-r--r-- 1 leb users    		29 Jul 28 15:20 junk
- $ *chmod -w copyofjunk*		# Make the copy hard to delete
- $ *ls -li *
- 14211 -r--r--r-- 1 leb users    		29 Jul 28 15:28 copyofjunk
- 14209 -rw-r--r-- 1 leb users    		29 Jul 28 15:20 junk
- $ *rm copyofjunk*				# rm will complain...
- rm: remove 'copyofjunk', overriding mode 0444? *y*

## Manipulating Files and Inodes(continued)

*mv(1) *renames files by moving links (using a combination of the *link(2) *and *unlink(2) *system calls)
- $ *mv junk samejunk*		# Move a link
- $ *ls -li *
- 14209 -rw-r--r-- 1 leb users    29 Jul 28 15:20 samejunk
*mv* also renames directories, effectively moving all files and subdirectories they contain
*mv* and cp have a special syntax for multiple files:
- $ *mv file1 file2 ... directory*
- $ *cp file1 file2 ... directory*
- Remember that . and .. are directories:
- $ *cp /etc/passwd /tmp/myfile .*

## Device Files

- UNIX treats *peripherals* as files
- There are two classes of device files
- “Block” devices (tapes and disks)
- “Character” devices (terminals, printers, serial ports, *etc.*)
- Denoted by ‘b’ and ‘c’, respectively, in an “*ls -l*” listing
- Device files are maintained in a table in the kernel
- The table is indexed by the *major* and *minor* numbers
- Major number denotes the kind of device
- Minor number denotes instances of the device
- The kernel translates calls to open, close, read, and write a device file into the hardware commands to control the device

## Device Files(continued)

- Device files are traditionally found in /dev
- $ *ls -l /dev*
- crw--w--w- 1 root      	0,  	0 	Sep 27 23:09 	console
- crw-r--r-- 1 root      	3,  	1 	Sep 27 14:37 	kmem
- crw-r--r-- 1 root      	3,  	0 	May  6, 1981 	mem
- brw-r--r-- 1 root      	1, 	64 	Aug 24 17:41 	mt0
- crw-rw-rw- 1 root     	3,  	2 	Sep 28 02:03 	null
- crw-rw-rw- 1 root      	5,  	0 	Jul  5 08:04 	tty
- crw--w--w- 1 root      	4,  	0 	Sep 28 02:38 	tty0
- crw--w--w- 1 root      	4,  	1 	Sep 27 23:09 	tty1
- brw-r----- 1 root      	8,  	0 	Sep  8 08:07 	sda
- brw-r--r-- 1 root      	8,  	1 	Sep  8 08:07 	sda1
- brw-r--r-- 1 root      	8,  	2 	Sep  8 08:08 	sda2

## Disk Devices

- Disk devices are usually named after the kind of drive
- For example, */dev/sda *is _S_CSI _D_isk _A_
- Disks are divided into *partitions*
- /dev/sda1   /dev/sda2
- Each partition is mounted, or attached, to a directory
- $ */sbin/mount*
- /dev/sda1 on /
- /dev/sda2 on /usr
- Each partition contains its own *file system*
- A file system is a complete collection of Inodes, directories, and file blocks
- Inode numbers are not unique on different file systems, so links between file systems are not allowed
- $ *ln /bin/mail /home/class/mail*
- ln: Cross-device link

## Terminal Devices

- While loging in a terminal, or *tty*, line is assigned
- $ *tty*
- /dev/tty1
- $ *ls -l /dev/tty1*
- crw--w--w- 1 class       4,  1 Sep 27 02:39 /dev/tty1
- $ *date >/dev/tty1*
- Wed Sep 27 02:39:45 EDT 1994
- tty is owned by the user, with read & write access
- All others have write access, to send messages
- $ *echo Greetings Earthling >/dev/tty3*
- The  mesg(1) command changes write access for others
- The file /dev/tty is a synonym for whatever terminal is assigned when you login

## The NULL Device

*/dev/null *is a “bit-bucket”, anything written to that file is quietly discarded, reads return an end-of-file
- Can be used to discard standard output to reveal only standard error
- $ *time grep e /usr/dict/words >/dev/null*
- real    13.0
- user     9.0
- sys      2.7
-    This example discards output of *grep(1) *to reveal only the output of *time(1)*, which writes its output to stderr

## Yet More Shells

- Terminal-mode C Shell, *tcsh*
- Sometimes pronounced “Taco-shell”
- Adds command line editing, and some addtional control features
- Bourne-Again Shell, *bash*
- Distributed by Free Software Foundation under GNU Public License
- Based on Bourne Shell, with command history, command line editing and many other features
- Other Shells, *ash, zsh*, *et al.*
- Offer more, fewer, and/or different features
- Choice of shell is a personal decision
- This course is based on Bourne Shell, which is available on every UNIX system

## Shell Metacharacters

- “Metacharacters” have a  special meaning to the shell
- They control input, output, sequencing and conditional execution of commands
- They provide convenient “shorthand” for file names
- Filename expansion wildcards replace explicit filenames
- * matches zero or more characters
- ? matches exactly one character
- By convention, expansion avoids filenames that begin with “.” (like the directories, “.” and “..”)
- $ *echo .***	*# all files that begin with .
- Question: in the following...
- $ *rm **
-    Why can’t rm warn you that you are about to delete all files?

## Table of Metacharacters

- >*file*		direct stdout to *file*
- >>*file*		append stdout to* file*
- <*file*		take stdin from  *file*
*p1 | p2*		connect stdout of program *p1* to stdin of program *p2*
*n*>*file*		direct output from file descriptor (filedes) *n* to file
*n*>>*file*		append output from filedes *n* to file
*n*>&*m*		merge output from filedes *n* with filedes *m*
*n*<&*m*		merge input from filedes *n* with filedes *m*
- <<*str*		*here document*; stdin follows, up to next *str* on a line by itself
- <<\*s*		here document with no substitution
- <<'*s*'		here document with no substitution
- *			match 0 or more characters in filenames
- ?			match any 1 character in filenames
- [*ccc*]		match any 1 character from *ccc* in filenames;
- 			ranges like 0-9 or a-z allowed

## Table of Metacharacters(continued)

- ;			command terminator; *p1 *;* p2 *runs p1, then p2
- &			like ; but doesn’t wait for p1 to finish
- `...`			run commands in ...; output replaces `...`
- (...)			run commands in ... in a sub-shell
- {...}		run commands in ... in current shell
- $1, $2, ...		$1 ... $9 replaced by arguments to shell file
- $*var*		value of shell variable *var*
- ${*var*}		value of shell variable *var* when concatenated to text
- \			\*c* takes character *c* literally; \*newline* discarded
- '...'			take ... literally
- "..."			take ... literally after $, `...`, and \ interpreted
- #			if # starts a word, rest of line is a comment
*var*=*value*		assign to variable *var*
*p1* && *p2*		run *p1*; if successful, run *p2*
*p1 || p2*		run *p1*; if unsuccessful, run *p2*

## Quoting

- Metacharacters are “protected” by ...
- Preceding _each_ metacharacter with a backslash, \
- $ *echo \?\?\?**	*# echo three question marks
- Enclosing in single quotes
- $ *echo '*'**	*# echo a single asterisk
- Enclosing in double quotes
- $ *echo "***"**	*# echo three asterisks
- The shell “peeks” inside double quotes to look for dollar signs, $, backquotes, `, and backslashes, \
- Quoted strings can contain newline characters
- $ *echo 'hello*
- > *world'*
- hello
- world
- $

## Continuations and Comments

- A backslash at the end of a line ‘quotes’ the newline, continuing the command
- $ *echo abc\*
- > *def\*
- > *ghi*
- abcdefghi
- Note that the newline is discarded from the input
- A hash symbol delimits a comment
- $ *echo hello # there*
- hello
- $ *echo hello#there*
- hello#there
- Note that the hash symbol must be preceded by whitespace

## Creating New Commands

- Shell programs are text files containing UNIX commands
- All shells provide normal programming constructs
- Variables
- Conditional execution
- Loops
- Shell programs are best suited for:
- Repetitive tasks
- File manipulation (moves, copies, backups, *etc.*)
- Administrative tasks (checking mail, running complex programs, *etc.*)
- Text processing
- Filters to transform or analyse files
- Creating new files automatically, including new shell programs

## Creating New Commands(continued)

- New commands (called _*scripts*_) are created with an editor (vi or emacs)
- _Very_ good typists can use *echo*
- $ *echo 'who | wc -l' >nu*
- Without qoutes, what would be in *nu*?
- Scripts need to be *executable*
- $ *chmod +x nu*
- $ *who*
- leb      tty1     Aug 17 12:35
- root     tty3     Aug 17 12:36
- class    tty2     Aug 17 12:35
- $ *nu*
- 3

## PATH Environment Variable

- For personal scripts, keep a personal library
- The shell finds commands by searching the *PATH *variable
- $ *echo $PATH*
- /usr/local/bin:/bin:/usr/bin
- $ *pwd*
- /home/class
- $ *mkdir bin*
- $ *PATH=/home/class/bin:$PATH*
- $ *echo $PATH*
- /home/class/bin:/usr/local/bin:/bin:/usr/bin
- $ *mv nu bin*
- $ *ls nu*
- ls: nu: No such file or directory
- $ *nu*
-      3

## Exercise 1. Finding shell scripts

- Look in /bin and */usr/bin *to see how many files are shell scripts.  Can you do it with one command (*i.e. *pipeline)?
- Hint:  Look at *file(1)*

## Arguments and Parameters

- Usually, a script needs to be given *arguments*
- file names, search strings, options, *etc.*
- Built-in variable $* represents _*all*_ the arguments
- $1, $2, ..., $9 represents the first 9 args
- Built-in command, *shift*, moves all args one space “to the left”
- $ *cat shift_echo*
- echo $1 $2 $3 $4
- shift
- echo $1 $2 $3 $4
- shift
- echo $1 $2 $3 $4
- $ *shift_echo This is a Test of Shift*
- This is a Test
- is a Test of
- a Test of Shift

## Example: 411, directory information

- Consider a phone book:
- $ *cat /home/class/lib/phone-book*
- Front Desk   441-4000
- Lee Hingle   794-5094
- Accounting   794-5540
- Lee Brotzman 776-0324
- Create a very simple search program:
- $ *cat 'grep $* /home/class/lib/phone-book' >411*
- $ *chmod +x 411*
- $ *411 Accounting*
- Accounting   794-5540
- $ *411 Lee*
- Lee Hingle   794-5094
- Lee Brotzman 776-0324
- $ *411 Front Desk*
- grep: Desk: No such file or directory
- Something is wrong!?  What, and how can it be fixed?

**Notes:**
The problem is that the bare $* given in the 411 program is being expanded into two arguments.  The first argument is the pattern to search for, and the second, 'Desk', in this case, is taken as the first in a list of files to search.  The program should be modifed, with double quotes around the argument, as in:
grep "$*" /home/class/lib/phone-book
The double quotes are "transparent" to the shell in that they allow for the expansion of the $* argument, but all characters, including spaces, in the quoted string are passed to the program as a single string.
Another useful change would be to make the search case-insensitive:
grep -i "$*" /home/class/lib/phone-book

## Program Output as Arguments

- Arguments can be *created* from the output of other commands by enclosing the command in backquotes
- $ *echo At the tone the time will be `date`*
- At the tone the time will be Mon Aug 15 16:40:20 EDT 1994
- Backquotes are interpreted inside double quotes
- Example: cheap mailing lists
- $ *cat mailinglist*
- echo john paul george ringo
- $ *chmod +x mailinglist*
- $ *mailinglist*
- john paul george ringo
- $ *mail `mailinglist` <new_song*

## Shell Variables

- Shells have variables (parameters) like other languages
*Positional Parameters:    $1, $2, ..., $9*
*Environment Variables:  $HOME, $PATH, etc.*
- Variables are assigned with an equals sign
*No spaces are allowed before or after the equals sign*
*$ PATH=/bin:/usr/bin:/home/class/bin*
- Variables are referenced by preceding with a dollar sign
*$ PATH=$PATH:/usr/games**	**# Add /usr/games to PATH*
*$ echo $PATH*
*/bin:/usr/bin:/home/class/bin:/usr/games*
- The set command displays all of the currently set variables

## Exporting Shell Variables

- Variables are associated with the shell that creates them, not subshells (like shell scripts)
- $ *x=Hello*
- $ *echo $x*
- Hello
- $ *sh*		# Run a new shell
- $ *echo $x**	*# Variable x isn’t there!
- $ *exit**	**	*# Leave the subshell
- The shell is told to copy variables to subshells with the *export* command
- $ *export x*
- $ *sh*
- $ *echo $x*
- Hello
- $ exit

## Modifying Shell VariablesThe . command

- The . (dot) command will run a shell script _*in the current shell*_, not in a subshell
- Commonly used to reexecute the *.profile *startup script without logging in again
- $ *cat chvar*		# Change the value of variable x
- x=$1
- echo $x
- $ *echo $x**	**	*# What is x now?
- Hello
- $ *chvar Goodbye**	**	*# Change x to "Goodbye" -- NOT!
- Goodbye
- $ *echo $x**	**	*# See?  It didn't change in the current shell
- Hello
- $ *. chvar Goodbye*		# Now execute chvar in the current shell
- Goodbye
- $ *echo $x**	**	*# And x actually gets changed
- Goodbye

## Here DocumentsInput from within a Shell script

- A shell script can provide a standard input stream from within the script itself, using the << metacharacters
- A new version of the 411 program makes it self-contained
- $ *cat new411*
- grep -i "$*" <<End
- Front Desk   441-4000
- Lee Hingle   794-5094
- Accounting   794-5540
- Lee Brotzman 776-0324
- End
- $ new*411 lee*
- Lee Hingle   794-5094
- Lee Brotzman 776-0324
- The shell substitutes for $, `...`, and \ unless the here document marker is quoted or preceded by a \

## Looping in Shell Programs

- The *for* loop is provided for looping over the items in a list, such as filenames:
- A simple example, echo all filenames one per line
- $ *for i in **
- > *do*
- > 	  *echo $i*
- > *done*
- This multi-line format can be condensed to one line
- $ *for i in *; do echo $i; done*
- The i can be any variable name.
- Note that *for* refers to a bare variable name, *i*, while inside the loop, the variable is referred to as *$i*

## Looping in Shell Programs(continued)

- When writing scripts, be aware of commands that already loop over a list of files
- BAD	for i in $*
- 		do
- 		   chmod +x $i
- 		done
- GOOD	chmod +x $*
- Know the difference between
- for i in *	   and       for i in $*
- The list can come from anywhere, not just file wildcards
- for i in `cat users`
- do
- 		finger $i
- 		echo ------------------------
- done >user-report

## Putting it all together

- Script *bundle* concatenates files in a way that the shell can later extract them, for sending files through the mail, for instance
- # bundle:  group files into a distribution package
- echo '# To unbundle, sh this file'
- for i in $*
- do
-    echo "echo $i 1>&2"
-    echo "cat >$i <<'End of $i'"
-    cat $i
-    echo "End if $i"
- done

## Filters

- Filters are programs that accept data on standard input, process it, and write the modified data to standard output.
- How many unique lines are in all of my data files?
- $ cat *.dat | sort | uniq | wc -l
*grep* is one of the most often used filters
- Uses “regular expressions” as patterns for matching text
- Has many options for altering the kind of output generated
*sed* and *awk* are general purpose programmable filters
*sed* stands for “stream-editor”, it uses a “program” of *ed* (line editor) commands to transform data as it streams by
*awk*, named after the authors, is a more complete programming language, including variables, arithmetic, control flow, *etc.*

## Other Filters

- UNIX comes with a myriad of small single-purpose filters
- Better to do one thing fast and well than many things slowly and badly
- Combining many small filters is easier than programming one big one
*head(1) *and *tail(1) *list the start or end of files, respectively
*cut(1) *returns specified columns from the input, *paste(1) *puts files together in columns.
*uniq(1) *returns only unique lines from the input
*tr(1) *transliterates characters
- $      # "fold" lowercase to upper case
- $ *tr a-z A-Z* <lower.txt >upper.txt

## sort

*sort* is one of the more useful filters
- Many switches to control the sorting process
- -f 	“Fold” upper and lower case
- -d 	“Dictionary order” - ignore all but letters, digits and blanks
- -r 	Sort in reverse order
- -n 	Sort by numeric value, rather than by ASCII collating sequence
- +n 	Sort within a column n
- Examples
- $ *ls -l | sort +3nr*		# sort by byte count, largest first
- $ *sort -d phone-book*	# dictionary order, Dewitt after de Kalb

## Stream Editor, sed

*sed(1) *was originally derived from *ed(1)*, the original UNIX line-oriented text editor
- Basic command is simple:
- $ *sed 'list of ed commands' filenames* ...
- reads a line at a time
- applies each command to the line, in order
- writes the edited line to standard output
- without a list of filenames, sed edits standard input
- Has *-f  *switch to include sed commands from an external file

## Sample sed Commands

- Convert all instances of 'UNIX' to 'UNIX(TM)'
- $ *sed 's/UNIX/UNIX(TM)/g' class.txt >class.new.txt*
- List userids and login times
- $ *who | sed 's/ .* / /'*
- Print the header of a mail message (up to the first blank line)
- $* sed '/^$/q' mail.msg *
- Delete the header of a mail message
- $ *sed '1,/^$/d' mail.msg >mail.body*
- Print only the lines containing an E-mail address (userid@host)
- $ *sed -n '/ [^ ]+@[^ ]+/p'*
- -n switch tells sed to print _only_ with explicit print commands (p)
- Doublespace a document (insert an extra newline)
- $ *sed 's/$/\*
- > */'*

## Summary of sed Commands

- a\			append lines to output until one not ending in \
- b *label*		branch to command : *label*
- c\			change lines to following text as in a command
- d			delete line; read next input line
- i\			insert following text before next output
- l			list line, making all non-printing characters visible
- p			print line
- q			quit
- r *file*			read *file*, copy contents to output
- s/*old*/*new*/*f*		substitute *new* for *old*.  If *f*=g, replace all occurrences;  *f*=p, print; *f*=w file, write to *f**	**	**	**ile*
- t *label*		test; branch to *label* if substitution made to current line
- w *file*		write line to *file*
- y/*str1*/*str2*/		replace each character from *str1* with corresponding character from *str2* (no ranges 			allowed)
- =			print current input line number
- !*cmd*		do sed *cmd* only if line is not selected
- : *label* 		set label for b and t commands
- {			treat commands up to matching } as a group

## Exercise: sed

- Modify the sample *sed* command to list userids and login times so that the login times appear at the beginning of the line, *e.g.*
-    		$ *who | sed *...
-   			11:14 root
-    			10:52 class
-    			09:39 leb
- Hint: remember tagged regular expressions from *grep*

**Notes:**
The answer I got was:
$ who | sed ‘s/ .* / /
> /\(.*\) \(.*\)/\2 \1/’

## awk pattern scanning and processing language

*awk* overcomes some of the limitations of *sed*
- arithmetic and builtin functions
- variables and arrays
- control flow (if, for, while)
- Basic *awk  *programs are lists of patterns and actions, which are applied to each line of the input in turn
*pattern* { *action* }
*pattern* { *action* }
- Patterns in *awk* can be regular expressions, ala sed
- $ *awk '/[^ ]@[^ ]/ { print }' mail.msg*
- Patterns can be logical expressions
- $ *awk 'NF == 1 { print $1 }' test.dat*
- prints lines with only one field

## awk(continued)

*awk* automatically splits each input line into fields, called *$1, $2, ... $NF*, where *NF* is a variable set to the total number of fields.
- Here is an easier way to print the login times and userids from our exercise in sed programming:
- $ *who | awk '{ print $5, $1 }'*
- The *-Fc *switch sets the field delimiter from whitespace (blanks and tabs) to the character *c*
- $ *awk -F: '{ print $1, $7 }' /etc/passwd*
- prints userids and the shells they use
- Two special "patterns", *BEGIN* and *END* match the beginning and end of the file, respectively
- Normally used for initialization and cleanup

## awk Arrays

- Arrays are allowed as in other languages
- $ *cat backwards*
- # backwards: print output in reverse line order
- awk '{ line[NR] = $0 }
- END  { for (i = NR; i > 0; i--) print line[i] }' $*
- _Associative arrays_ are indexed by _strings_ rather than by numbers
- $ cat wordfreq
- # wordfreq: print word counts from input
- awk '{ for (i = 1; i <= NF; i++) num[$i]++ }
- END  { for (word in num) print num[word], "  ", word }
- ' $* | sort -nr

## sed and awk

- There is much more to say about *sed* and especially about *awk*
- Get the O'Reilly and Associates book for sed and awk programming
*sed* is generally useful for quick general purpose filters to supplement those already provided by every typical UNIX
*awk* is a powerful, full-fledged text processor and report generator, with a rather complete suite of features and tools

## Bourne Shell Programming

- The Bourne shell is the original UNIX shell.
- It is available on _all_ variants of UNIX, unlike the C shell (csh).
- The Korn Shell is compatible on a source code level with Bourne shell.
- The Bourne-Again Shell (bash) is a popular replacement from the Foundation for Software Freedom (FSF).
- The features studied here are the most basic elements of the shell, see the man pages and the text for more detailed information.

## Shell Built-In Variables

- $# 		the number of arguments
- $* 		all arguments to shell
- $@ 	similar to $*, explained in detail later
- $- 		options supplied to the shell
- $? 		return value of the last command executed
- $$ 		process-id of the shell
- $! 		process-id of the last command started with &
- $HOME 	default argument for cd command
- $IFS 	list of characters that separate words in arguments
- $MAIL 	file that, when changed, triggers "you have mail" message
- $PATH 	list of directories to search for commands
- $PS1 	prompt string, default '$ '
- $PS2 	prompt string for continued command line, default '> '

## The set command

*set* is a builtin shell command that does too much
- by itself prints values of current variables
- with ordinary arguments, it resets $1, $2, etc. to those arguments
- Several options are available (depending on the implementation).  These are good for debugging:
- -e    cause the shell to exit when a command terminates with 	non-zero status
- -n    read commands but don't execute (used to check syntax)
- -v    print shell input lines as they are read
- -x    after expanding commands, display command and 		expanded arguments

## case Statements

*case* statements allow for selecting one of several choices
- case *word* in
*pattern*) *commands* ;;
*pattern*) *commands* ;;
- ...
- esac
- compares *word* to each of the patterns in turn and executes the commands for the first match found
- Efficient way to check arguments
- case $# in
- 0)	echo "Usage: $0 args..." ; exit 1 ;;
- 1)  arg1=$1; arg2="default" ;;
- *)  arg1=$1; arg2=$2 ;;
- esac

## Shell Pattern Matching Rules

- *		match any string, including the null string
- ?		match any single character
- [ccc]	match any of the characters in ccc, ranges are allowed
- "..."	match ... exactly; quotes protect special characters.  Also '...'
- \c		match c literally
- a|b		in case expressions only, matches either a or b
- /		in filenames, matched only by an explicit / in the expression; in 	case, matched like any other character
- .		as the first character of a filename, is matched only 		by an explicit . in the expression

## Example case Statements

- # cal: nicer interface to /usr/bin/cal, with month names
- case $# in
- 0)      	set `date`; m=$2; y=$6 ;; 		# no args: use today
- 1)     	m=$1; set `date`; y=$6 ;; 		# 1 arg: use this year
- *)      	m=$1; y=$2 ;;             		# 2 args: month and year
- esac
- case $m in
- jan*|Jan*)      	m=1 ;;
- feb*|Feb*)      	m=2 ;;
- ...
- dec*|Dec*)      	m=12 ;;
- [1-9]|10|11|12) 	;;              		# numeric month
- *)              		y=$m; m="" ;;   	# plain year
- esac
- /usr/bin/cal $m $y             		 # run the real cal program

## Control flow: which command?

- In the next few slides we will use some basic control flow structures to determine where in the PATH a command can be found, *e.g.*
- $ *which ls*
- /bin/ls
- $ *which cut*
- /usr/bin/cut
- Basic algorithm:
-  		for i in *each component of PATH*
-  		do
-   		 *if given name is in directory i  print its full pathname*
-  		done
- First, we need to get a list of the PATH directories

## which command? PATH elements

- In the PATH, “::” is equivalent to “:.:”, as is a bare “:” at the beginning or end of the PATH list
- $ *echo $PATH*
- /bin:/usr/bin:/home/class/bin:
- We use *sed* to change each “:” to a blank, taking into account the “phantom dot” directory, if it exists
- $ *echo $PATH | sed 's/^:/.:/*
- >                   *s/::/:.:/g*
- >                   *s/:$/:./*
- >                   *s/:/ /g'*
- /bin /usr/bin /home/class/bin .

## Conditional execution: if

- Basic structure
- if *command*
- then
- 		*commands if condition true*
- else
- 		*commands if condition false*
- fi
- UNIX commands return a status of 0 (true) on success or nonzero (usually 1 for false) on failure.
- $ *if who | grep class >/dev/null*
- > *then*
- >   *echo "Class logged on"*
- > *fi*
- The status code returned by a pipeline is that of the last command in the pipe

## Testing Things

*test(1) *returns a true/false based on some condition
- 	-d *file*		True if file exists and is a directory
- 	-e *file*		True if file exists
- 	-f *file*		True if file exists and is a regular file
- 	-r *file*		True if file exists and is readable
- 	-s *file*		True is file exists and has a size greater than zero
- 	-w *file*		True if file exists and is writable
- 	-x *file*		True if file exists and is executable
- 	-z *string*		True if the length of string is zero
- 	-n *string*		True if length of string is nonzero
- 	*string*		True if length of string is nonzero
- 	*string1* = *string2* 	True if strings are equal
- 	*string1* != *string2* 	True if strings are not equal
- 	! *expr* 		True if expr is false
- 	*expr1* -a *expr2* 	True if both expr1 and expr2 are true
- 	*expr1* -o *expr2* 	True if either expr1 or expr2 are true
- 	*arg1* OP *arg2* 	Where OP is -eq, -ne, -lt, -le, -gt or -ge
- 			True if numeric values meet condition

## test continued

*test* and its synonym, [, are usually builtin operators of the shell
- [ requires a closing bracket, ]
- if [ -r /home/class/lib/phone-book ]
- then
- 		grep -i "$*" /home/class/lib/phone-book
- else
- 		echo Call 441-4000 for information
- fi
- For our *which* command, we want to find executables
- if [ -x *file in PATH directory* ]
- then
- 		echo *complete pathname*
- fi

## Which Command? which

- # which cmd:  which cmd in PATH is executed
- case $# in
- 0)      echo "Usage: $0 command" 1>&2; exit 2
- esac
- for i in `echo $PATH | sed 's/^:/.:/
-                           s/::/:.:/g
-                           s/:$/:./
-                           s/:/ /g'`
- do
-        if [ -x $i/$1 ]
-        then
-                echo $i/$1
-                exit 0
-        fi
- done
- exit 1

## for loops revisited

*for* is the most common loop, iterating over a list of items
- There are two basic forms, the one we’ve seen:
- for i in *list of words*
- do
-    *loop body, $i set to successive elements of list*
- done
- And one specifically for looping over the input arguments
- for i    *(List is implicitly all arguments, i.e. $*)*
- do
-    *loop body, $i set to successive elements of list*
- done

## while and until loops

***while***** and *****until***** loops use the exit status of a command to control termination of the loop**
***while***** and *****until***** complement each other in interpretation of the exit status**
**while continues looping if the exit status is true**
**until continues looping if the exit status is false**
**Basic structure**
**[while|until] *****command***
**do**
**   *****loop body***
**done**

## Example: while and until

- The following two examples do the same thing: wait for user *class* to log in
- while sleep 60
- do
-        who | grep class
- done
- until who | grep class
- do
-        sleep 60
- done
- Which do you prefer and why?
- Remember that the exit status of a pipeline is the status of the last command in the pipe

## Exercise: looping

- Use an until loop to watch for a _list of users_ given on the command line.  The script will exit when any one of the users logs in.
- Hint: this will require egrep regular expressions and a sed filter.

**Notes:**
The answer I got was:

# watchfor: look for a list of users
PATH=/bin:/usr/bin
case $# in
0)      echo "Usage: $0 users ..." 1>&2; exit 1
esac
until who | egrep `echo $* | sed 's/ /|/g'`
do
       sleep 10
done

## Evaluation of shell variables

- $var		value of *var*; nothing if *var* undefined
- ${var}		same; useful if alphanumerics follow variable name
- ${var-value}	value of *var* if defined; otherwise value.  *$var *			unchanged
- ${var=value}	value of *var* if defined; otherwise value. If undefined, 			*$var *set to value
- ${var?message}	if defined, *$var*.  Otherwise, print message and exit 			shell.  If message empty, print default message 			"parameter not set"
- ${var+value}	value if *$var *defined, otherwise nothing
- Take a few moments to try some of these by setting variables and echoing them (or echoing non-existent variables)

## Accepting User Input: read

*read* reads in one line of input from standard input and assigns the text(without a newline) as the value of the named variable
- $ *read something*
- Hello, world
- $ *echo $something*
- Hello, world
- Older versions of the shell did not allow redirection of standard input (read is a builtin command)
- Modern shells allow redirection, but not with pipes.
- $ *echo $upper*
- ALL UPPER CASE
- $ *echo $upper | tr A-Z a-z | sed 's/upper/lower/' >/tmp/var*
- $ *read lower </tmp/var*
- $ *echo $lower*
- all lower case

## Traps: catching interrupts

- If a shell script is interrupted by a ^C or some other signal, any temporary files will be left behind
- Need to "catch" the interrupt signal, cleanup anything that needs it, and exit
- Basic command:
*trap* *sequence-of-commands* *list-of-signal-numbers*
- Example: clean up a temporary file on receiving an interrupt or terminate signal
*trap 'rm -f /tmp/tmpfile; exit 1' 1 15*
- See the next slide for common signal numbers

## Shell Signal Numbers

- 0		shell exit (for any reason, including end of file)
- 1		hangup
- 2		interrupt (^C)
- 3		quit (^\; causes program to produce core dump)
- 9		kill (cannot be caught or ignored)
- 15	terminate, default signal generated by kill(1)

## Aliases

- Most implementations of shells allow for *aliases*
- Commonly used to set default switches for commands
- alias ls='ls -F'
- alias ll='ls -l'
- alias rm='rm -i'
- Can be used to string several commands together
- alias dir='pwd; ls -l'
- alias logout='clear; exit'
- alias whoops='ps -axu | grep'
- Any arguments following the alias are appending to the replacement text after the alias is expanded
- However, _there is no mechanism for using arguments within the replacement text_
- If arguments are needed, use a shell function

## Shell Functions

- Modern versions of the Bourne shell allow functions
- Functions store a series of commands for later execution
- Functions declared in .profile are available as interactive commands, like aliases
- Functions are executed in the context of the current shell; not a subshell
- Arguments to the function become positional parameters, $1, $2, ...
- After the function exits, the original positional parameters are restored
- Variables local to the function can be declared by “*local*” builtin command
- These variables exist only during the execution of the function

## Example Shell Function

- Rename a list of files to all lowercase characters
- tolow()
- {
- 		for i
- 		do
- 		    mv $i `echo $i | tr [A-Z] [a-z]`
- 		done
- }
*e.g.*
- $ *ls*
- This      That      TheOther
- $ *tolow *; ls*
- this      that      theother
- What happens if the filename is already all lowercase?
- How can this behavior be avoided?

## Example Shell Function(continued)

- Repeat a command:
- Usage:  repeat *n  command*
*e.g.*:       repeat 80 echo -n "-"
- 	  repeat()
- {
- 	local count=$1
- 	shift
- 	while [ "$count" -gt 0 ]
- 	do
-  		$*
-  		count=`expr $count - 1`
- 	done
- }
- Note:  This function is _really slow_.  Repeated arithmetic with *expr* takes a lot of CPU time.

## Style

- Use script “magic number” to unambiguously identify the shell
- #!/bin/sh
- _Use liberal comments!_
- Use tabs and blank lines for readability
- Keep things simple if at all possible
- Use several small single-purpose scripts, not one large general- purpose one
- Try to keep a UNIX “flavor”
- Print Usage message if arguments are required but not supplied
- Keep intermediate (“OK to here, Bob”) messages to a minimum
- Use proper exit status for success (0) or failure (1 or some other nonzero value)