Related Book Recommendations
PPT Slide
Expansion, Globbing, Pipelines,
Computer Science & Engineering
http://www.cs.washington.edu/uns/ToolsTalks/Shell.html
PPT Slide
PPT Slide
- Redirection and Pipelines
- Job control, completion control, line editor keybindings
PPT Slide
- Common and important interaction method
- Interface to OS, especially to exec
- manages environment variables
- creates argument lists
- opens file descriptors and pipelines
- controls processes
-
- Shell does more than you might think
- lots of substitutions, expansions
- Shell does less than you might think
- not ls, ps, env other simple commands
PPT Slide
cat $MDIR/notes.* ~/letters.* > Notes
- Filename (tilde) expansion
- Generates list of filenames (globbing)
- Pre-opens fd 1 (stdout) for I/O redirection
- Context of the current working directory
-
- argc = 4
- argv[0] = "cat"
- argv[1] = "/home/gjb/Mail/notes.1"
- argv[2] = "/home/gjb/Mail/notes.2"
- argv[3] = "/home/gjb/letters.foo"
-
- and stdout goes to Notes
PPT Slide
cat $MDIR/notes.* ~/letters.* > Notes
- no files matching /home/gjb/Mail/notes.* ?
- no files matching /home/gjb/letters.* ?
- directory exists named /home/gjb/letters.bak/
- already a file names Notes
PPT Slide
cat $MDIR/notes.* ~/letters.* > Notes
- $HOME not defined?
- Error in csh, empty expansion in sh
- no files matching /home/gjb/Mail/notes.* ? /home/gjb/letters.* ?
- Error if any don’t match
- or error if none match
- or remove from argument list
- or leave * unchanged
-
- directory exists named /home/gjb/letters.bak/
- already a file names Notes
- Clobber? Could be dangerous
- No clobber? Could be annoying
PPT Slide
- Zsh: http://sunsite.auc.dk/zsh/
- [T]csh:http://www.tac.nyc.ny.us/mirrors/tcsh-book/ esp. csh-whynot
chsh, passwd -s/e, or yppasswd -s
shell must be listed in /etc/shells
PPT Slide
Zsh is not in /etc/shells,
- Use csh, with .cshrc generated from your ~/.env(see make-cshrc-from-env)
- Csh gets used for rsh/ssh, when only a simple environment is needed (faster startup)
- Or just exec /uns/bin/zsh from first line of ~/.cshrc
- Be sure ~/.tcshrc does not exist
- Source your .env from your .xsession and from your .zshenv
PPT Slide
(-l or argv[0][0] == '-')
(-l or argv[0][0] == '-')
PPT Slide
(-l or argv[0][0] == '-')
(-l or argv[0][0] == '-')
Does $HOME/.tcshrc exist?
PPT Slide
(-l or argv[0][0] == '-')
PPT Slide
(and commonly used options)
- find . -{iname,size,exec,print}
- cvs {update,diff,status,log}
- sed, awk -[F], tr, cut, paste, join
- which, where (zsh), /uns/bin/witch
PPT Slide
- Environment variables
- e.g., $PATH, $HOME
- available to child processes
- only a string; lists simulated with :
- list them with env command
- means of setting options for programs
- exist separately from the shell
- e.g.,window manager can exec processes
-
- Regular shell variables
- e.g., $i, $PROCMAILDIR
- only available in shell
- may have more complex structure
-
- Special variables
- $?, $$, $#, $PWD "set" by shell
- $PROMPT "used" by shell
- $path is an array, e.g., $path[4], automatically mirrors $PATH
PPT Slide
foo=bar # just shell variable
export foo # now make env. var
export BAR=baz (not bare sh)
Csh variables hide environment variables
Note: no $ prefix when setting, it is a
notation for replacing the variable name
PPT Slide
- options (from command line)
- zsh has named options, too
-
- aliases
- alias ll ’ls -l’ (csh)
- alias print ’pr \!* | lpr’ (csh)
- alias mroe=’more’ (sh)
- \<command> avoids alias expansion
-
- functions
- title() { echo "^[]0;$*^G";}
-
- completion control
- zsh and tcsh, not csh or sh
- line-editing bindings
- bash just uses readline library
- tcsh and zsh have bindkey built-in
PPT Slide
Shells need to be able to create arbitrary argument lists.
Quoting lets us control exactly
PPT Slide
- Shells split on unquoted whitespace in input
- Handy program to display arguments:
int main(int argc, char **argv)
printf("argc = %d\n",argc);
for (i=0; i < argc; i++) {
printf("argv[%d] = \"%s\"\n",
% foo=test # or set foo=test
PPT Slide
# no space allowed after var name!
echo "argv[" $i "] = " $arg
PPT Slide
Shell Quoting \ vs "" vs ’’
\? escapes ? (suppresses shell meaning)
’...’ escapes all enclosed chars
"..." escapes all except $, \, ``
argc = 2; argv[0] = "args"; argv[1] = "Test bar baz"
argc = 2; argv[0] = "args"; argv[1] = "$foo bar baz"
$ is a special character, too
argc = 2; argv[0] = "args"; argv[1] = "$foo bar baz"
PPT Slide
whitespace [space, tab, newline]
$ Variable interpolation/
< > Redirection# Comment (not always when interactive)
PPT Slide
- Shells split on unquoted whitespace in input
- Single quotes are not special in double quotes
- Double quotes are not special in single quotes
% args "home is "\’"$HOME"\’
argv[1] = home is ’/homes/gws/gjb’
% args ’$foo’s value is $foo’
% args ’$foo\’s value is $foo’
Error -- \ has no special meaning in ’ ’
% args ’$foo’"’s value is $foo"
argv[1] = $foo’s value is Test
PPT Slide
argv[1] = this; argv[2] = is; ...
(except zsh, unless setopt shwordsplit)
% foo_array=(this is a test) #zsh
argv[1] = this; argv[2] = is; ...
PPT Slide
% find . -name "*~" -exec rm {} \;
What does find get for arguments?
% args . -name "*~" -exec rm {} \;
argv[6] = {} # ok because no space
*~ is subject to filename generation
; is the shell sequencing operator
% args . -name *~ -exec rm {} ;
argv[argc-1] = {} # ; got removed
PPT Slide
$foo can be written as ${foo}
setenv PATH /uns/bin:${PATH}:.
- trailing colons are modifiers in zsh, (t)csh
- zsh ignores bad modifiers, (t)csh complains
:substitute (e.g., $foo:s/.c/.o/)
% echo $foo:t:r ? args.c:r #csh
Use braces! Prefer ${foo:t:r}
PPT Slide
echo ${foo%.*} ? test.bar
Note: . is a literal; not regexp meta-character
% and # cause non-greedy match
%% and ## take the longest match
Sharp from start; percent from end
[..] = any of characters ..
[^..] = anything but characters ..
PPT Slide
1) history (interactive only)
e.g., !$ is last argument from prior line
^cat^more replace cat with more
2) alias; e.g., alias ll=’ls -l’
3) process substitution, variable expansion, command substitution, arithmetic expansion, brace expansion
(same time, left to right)
4) Removal of unquoted \, ’, "
5) filename expansion (could be after alias substitution if setopt sh_file_expansion)
PPT Slide
<event>:<word>[:<modifier>]+
!n command n (use history)
!<str> command starting with
!?<str> command containing
k argument k (0 for command name)
x-y arguments x through y
x- arguments x through $-1
% mv long_filename !#$.old
% ^update^commit # like !!:s/commit/update/
Often, prefer interactive line editing.
PPT Slide
`pipeline` ? stdout from pipeline
(Zsh and Bash allow $(pipeline) )
% cat `echo foo bar` ? cat foo bar
% cat $(echo foo bar)? cat foo bar
Advantage of $(..) is that they can be nested
stdout is split into arguments
% args `echo This is a test`
% args `echo This "is a" test`
% args "`echo This is a test`"
PPT Slide
% ls -d `cd /tmp/gjb; /bin/ls` 2>/dev/null
Lists filenames that are common between
the current directory and /tmp/gjb
-d is a switch to ls telling it not to list contents
of directories names in the argument list
Use /bin/ls to defeat aliasing of ls
(-F option would append file type marks to
the listing that would get in the way)
2>/dev/null redirects stderr (fd 2) to
standard device which throws away its input
PPT Slide
(Note args.o didn’t exist)
% head ~{gjb,billg,rms}/.profile
Could give file not found
Use a glob, too, to filter out non-existing files
% head ~{gjb,billg,rms}/.[p]rofile
% mv long_filename{,.old}
% echo ${^manpath}/**/*(.)
PPT Slide
$[ .. ] replaces .. with its evaluation as an expression (Zsh)
Other shells, use expr command, e.g.,
% set i=`expr $i + 1` # csh
let built-in evals args and returns 0 if last expression is nonzero
PPT Slide
~<username> ? home directory
~1 ? Top of the directory stack
=<cmdname> ? `which <cmdname>`
(text of aliases is used)
pushd and popd to manipulate it.
auto_pushd, pushd_silent,
Also: two argument form of cd/pushd
%cd gjb billg #cd `echo ~+ | sed s/gjb/billg`
PPT Slide
Filename Generation (Glob)
% file *.[ch] # character class
% test -f $i && cp $i ~/dots
Ignore *.o files (requires Zsh setopt extendedglob)
**/* All non-dot files under current directory
All files? Need a Zsh advanced glob modifier
Other shells: use something like:
find . -print0 | xargs -0 <cmd>
PPT Slide
*(g{grad_cs}) Group grad_cs
*(u{^root}) Not owned by root
*(mh-2) Changed in last 2 hours
All files owned by gjb, or
group uns and modified in last two hours
Directories with files bigger than 500kb
(or use setopt numeric_glob_sort)
PPT Slide
> Redirect stdout (use>> to append)
2> Redirect stderr (fd 2) (2>> to append)
>& Redirect stdout + stderr
(Also can append ! to force overwrite/create)
Zsh allows multiple ’<’s and copies the input
from the files successively.
Zsh allows multiple ’>’s and outputs a copy to
% awk ’{print $1}’ <foo <bar \
Note: \ escapes the newline for continuation
of a command line (like in C source)
PPT Slide
after stripping initial spaces
Use <<’FOO’ to suppress variable and
command substitution within the body.
% args <<<"This gets put on stdin"
(T)csh Redirection is broken
- stderr can not be redirected separately from stdout; must use the “subshell hack”
PPT Slide
% ps aux | grep xnewbiff |\
or, better (exec-s are expensive!)
% ps aux | awk ’/xnewbiff/ \
- Does not create a temporary file; uses popen system call and lets OS manage the buffers
- First process (producer) stalls if consumer is too slow (common for interactive consumers such as more and less)
PPT Slide
<(pipeline) Substitute a named pipe fed
>(pipeline) Pipe to given pipeline
=(pipeline) Substitute a temporary file
| tee >(sed ’s/foo/bar’ >out1)\
PPT Slide
Subshells vs. Command Lists
% rsh uni cat /tmp/arch/foo.tgz |\
(cd decompress; tar xvzf - )
% rsh uni cat /tmp/arch/foo.tgz |\
{cd decompress; tar xvzf - }
Subshell protects initial shell from
side-effects (in this case, cd)
Second doesn’t exec another shell, so is
faster, but can influence top level shell;
directory will be changed after pipeline is
e.g., copying a whole directory tree:
% (cd src; tar cf - . ) | \
PPT Slide
until ping -c 1 pahtoo; do
while ! ps aux | grep ical; do
continue and break act as in C
PPT Slide
Exit Codes (Return Values)
A process returns 0 to indicate successful completion, or non-zero to indicate failure
e.g., /bin/true returns 0; /bin/false, 1
(opposite of most other languages)
In Zsh, you can have it print non-zero exit values using setopt printexitvalue
Pipelines return the exit code of the consumer.
Conditionals simply test the exit codes, as do the short-circuiting && and || operators
% grep foo <in || echo "no foo"
% mkdir newdir && cd newdir
% test -f bar && ls >>bar
PPT Slide
% if [ "$foo" = test ]; then
[ is just another name for test which requires ] as its last argument
[ -t 0 ] true iff stdin is a tty (interactive)
(e.g., false from your .xsession)
[ -r readable ] [ -e exists ]
[ -f ordinary_file ] [ -d directory ]
[ -s non_empty (size > 0)]
Zsh also has [[ ]] special form, which allows patterns, and does not do an exec (faster)
% export PATH=$PATH:/uns/bin
PPT Slide
Trailing & on pipeline to run asynchronously
Ctrl-Z sends SIGSUSPEND, to pause
Ctrl-\ sends SIGABORT, to dump core
Use %<number> to refer to a pipeline
These are not expansions, only notation
understood by the job-control builtins!
PPT Slide
noglob like escaping all *, ?, [..]
exec do not fork, replace instead
command do not use builtin
var=val set only in child's environment
% HOME=/local/gjb xterm -e pine &|
PPT Slide
Ctrl-V in line editor quotes next char, e.g,
bindkey maps character sequences to command line editing functions (Tcsh/Zsh)
% bindkey "\e[k" backward-kill-line
% bindkey # shows key bindings
Bash uses readline, and its .inputrc
Xterm resources specify what keysyms send the appropriate control sequences:
XTerm*VT100*Translations: \
!Meta<Key>BackSpace: string("^[[k") \n\
PPT Slide
Other interactive features
% compctl -g ’*.dvi(D) *(-/D)’ \
% dirs; pushd; popd; cd -
May want setopt autopushd
PPT Slide
# $Id: outlinec.htm,v 1.3 1999/04/02 07:41:51 gjb Exp $
xrdb -cpp cpp-sed-nl "$@"
# $Id: outlinec.htm,v 1.3 1999/04/02 07:41:51 gjb Exp $ -*- zsh -*-
if [[ ! $# = "1" ]]; then
echo "Usage: $0 <file.man>" 1>&2
echo "Outputting to $OUT.ps" 1>&2
groff -Tps -mandoc $1 >| $OUT.ps
else # stdout is a pipe or a file
# so let stdout go as usual
PPT Slide
Script and Function Arguments
$0 name of program as exec-d
"$*" all arguments, as a string
"$@" all arguments, individually quoted
e.g., myscript foo bar baz
would set (inside myscript):
but "$@" == "foo" "bar" "baz"
Use "$@" to pass arguments to other pipelines
shift renames $2 to $1, $3 to $2, etc.
getopt built-in also can help with argument
PPT Slide
# cd to a new directory and ls
if [[ "" != "$1" ]]; then
if (( $# > 2 || $# == 0 )); then
print -u2 'Usage: add-path-better \ /some/dir [PATH_VARIABLE]'
2=PATH # default to using $PATH
pathval=`eval echo \\$${2}`
if [[ ":$pathval:" != *:${1}:* ]]; then eval "$2=\"\$$2:$1\""
$FPATH variable controls search for autoloaded functions (Zsh)
PPT Slide
Aliases vs. Functions vs. Scripts
- Aliases
- can inherit completion from expansion
- useful for adding default arguments
- poor at dealing with arguments% alias cp='cp -p'
-
- Functions
- do not require an exec, so faster
- often shell-specific
- can affect current environment
- hard to change due to caching in shell state
- refunc() { unfunction $1; autoload $1 }
- consumes memory (use autoload)
- special: precmd, chpwd, periodic (Zsh)
- Scripts
- more universal (not shell dependent)
- usable from window manager, Emacs
- cannot change current environment
- requires exec, but can choose language
PPT Slide
- Write scripts, aliases,functions as you need them
- User version control on your.zshrc-* files
- Read others’ configurations