.\" Notes on bash .TH bash pj "14 September 2006" .SH NAME bash .SH "BRACE EXPANSION TRICKS" .IP ${variable#pattern} Returns ${variable} with the shortest possible match of \fIpattern\fR cut off the front. .IP ${variable##pattern} Returns ${variable} with the longest possible match of \fIpattern\fR cut off the front. .IP ${variable%pattern} Returns ${variable} with the shortest possible match of \fIpattern\fR cut off the back. .IP ${variable%%pattern} Returns ${variable} with the longest possible match of \fIpattern\fR cut off the back. .PP If nothing matches, cut off nothing. Here are some examples: .PP .RS .nf $ f=a/b/c/d $ echo ${f##*/} d $ echo ${f%/*} a/b/c $ echo ${f%%/*} a .fi .RE .PP .SH LOGIN ~/.bash_profile is executed whenever a user logs in (or, on a Mac, whenever a new Terminal window is opened). ~/.bashrc is executed every time you start a non-login shell, as long as it is interactive. For non-interactive shells, neither file is executed. But if $BASH_ENV is set, a non-interactive shell will assume it specifies a file to run. Therefore you should set variables in ~/.bashrc, if you expect to have them in, e.g., cron. But if you set PATH recursively, e.g. PATH="$PATH:$HOME/bin", then it will get longer and longer. I'm not sure what to do about this conflict. .SH VARIABLES If unquoted, $* and $@ do the same thing. But if you put quotes around them, "$*" gives you one big argument, formatted like "$1 $2 $3 ..." If you set the IFS variable, the parameters will be separated by that value. If you set IFS to null, the parameters won't have any separation. .PP On the other hand, "$@" produces a separate argument for each positional parameter, with each one quoted. This is probably what you want, if you want to pass the user's arguments to an underlying program, since it preserves whatever quoting the user asked for. In other words, "$@" expands to "$1" "$2" "$3" ... .SH FUNCTIONS The return value of a function is not like in Perl or other languages. It is more like the return value of an executable: it sets $? and represents the function's status. If you want to return strings or arrays from a function, you should echo them instead and call the function in backticks. .SH FILES If you want to get file handles beyond 0, 1, and 2, you can use \fIexec\fR. Do something like this: .PP .RS .nf exec 3<&0 # now fd 3 points to stdin exec 0<"$filename" # now fd 0 reads from $filename \&. . . exec 0<&3 # restore old stdin exec 3<&- # close fd 3 .fi .RE .PP or just do this: .PP .RS .nf exec 3<> $filename .fi .RE .PP That opens $filename and assigns fd 3 to it. That way, you can aim any command at it, or read from it. .PP You should be careful not to use fd 5, which is inherited by child processes and left open. .SH LOOPS Suppose you want to iterate over the input from stdin. Then do something like this: .PP .RS .nf range 1 10 | sed -e 's/ /\\n/g' | while read i; do echo $i; done; .fi .RE .PP Of course just echoing the numbers is not that interesting. .SH AUTHOR Paul Jungwirth .SH COPYRIGHT Copyright \(co 2006 Paul Jungwirth