BUY THIS BOOK
Add to Cart

Print Book $49.99


Add to Cart

PDF $39.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £35.50

What is this?

Looking to Reprint or License this content?


bash Cookbook
bash Cookbook Solutions and Examples for bash Users

By Carl Albing, JP Vossen, Cameron Newham
Book Price: $49.99 USD
£35.50 GBP
PDF Price: $39.99

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Beginning bash
What's a shell, and why should you care about it?
Any recent computer operating system (by recent, we mean since about 1970) has some sort of user interface—some way of specifying commands for the operating system to execute. But in lots of operating systems, that command interface was really built in and there was only one way to talk to the computer. Furthermore, an operating system's command interface would let you execute commands, but that was about all. After all, what else was there to do?
The Unix operating system popularized the notion of separating the shell (the part of the system that lets you type commands) from everything else: the input/output system, the scheduler, memory management, and all of the other things the operating system takes care of for you (and that most users don't want to care about). The shell was just one more program; it was a program whose job was executing other programs on behalf of users.
But that was the beginning of a revolution. The shell was just another program that ran on Unix, if you didn't like the standard one, you could create your own. So by the end of Unix's first decade, there were at least two competing shells: the Bourne Shell, sh (which was a descendant of the original Thomson shell), plus the C Shell, csh. By the end of Unix's second decade, there were a few more alternatives: the Korn shell, (ksh), and the first versions of the bash shell (bash). By the end of Unix's third decade, there were probably a dozen different shells.
You probably don't sit around saying "should I use csh or bash or ksh today?" You're probably happy with the standard shell that came with your Linux (or BSD or Mac OS X or Solaris or HP/UX) system. But disentangling the shell from the operating system itself made it much easier for software developers (such as Brian Fox, the creator of bash, and Chet Ramey, the current developer and maintainer of bash), to write better shells—you could create a new shell without modifying the operating system itself. It was much easier to get a new shell accepted, since you didn't have to talk some operating vendor into building the shell into their system; all you had to do was package the shell so that it could be installed just like any other program.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Why bash?
Why is this book about bash, and not some other shell? Because bash is everywhere. It may not be the newest, and it's arguably not the fanciest or the most powerful (though if not, it comes close), nor is it the only shell that's distributed as open source software, but it is ubiquitous.
The reason has to do with history. The first shells were fairly good programing tools, but not very convenient for users. The C shell added a lot of user conveniences (like the ability to repeat a command you just typed), but as a programming language it was quirky. The Korn shell, which came along next (in the early 80s), added a lot of user conveniences, and improved the programming language, and looked like it was on the path to widespread adoption. But ksh wasn't open source software at first; it was a proprietary software product, and was therefore difficult to ship with a free operating system like Linux. (The Korn shell's license was changed in 2000, and again in 2005.)
In the late 1980s, the Unix community decided standardization was a good thing, and the POSIX working groups (organized by the IEEE) were formed. POSIX standardized the Unix libraries and utilities, including the shell. The standard shell was primarily based on the 1988 version of the Korn Shell, with some C shell features and a bit of invention to fill in the gaps. bash was begun as part of the GNU project's effort to produce a complete POSIX system, which naturally needed a POSIX shell.
bash provided the programming features that shell programmers needed, plus the conveniences that command-line users liked. It was originally conceived as an alternative to the Korn shell, but as the free software movement became more important, and as Linux became more popular, bash quickly overshadowed ksh.
As a result, bash is the default user shell on every Linux distribution we know about (there are a few hundred Linux distros, so there are probably a few with some oddball default shell), as well as Mac OS X. It's also available for just about every other Unix operating system, including BSD Unix and Solaris. In the rare cases where
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The bash Shell
bash is a shell: a command interpreter. The main purpose of bash (or of any shell) is to allow you to interact with the computer's operating system so that you can accomplish whatever you need to do. Usually that involves launching programs, so the shell takes the commands you type, determines from that input what programs need to be run, and launches them for you. You will also encounter tasks that involve a sequence of actions to perform that are recurring, or very complicated, or both. Shell programming, usually referred to as shell scripting, allows you to automate these tasks for ease of use, reliability, and reproducibility.
In case you're new to bash, we'll start with some basics. If you've used Unix or Linux at all, you probably aren't new to bash—but you may not have known you were using it. bash is really just a language for executing commands—so the commands you've been typing all along (e.g., ls, cd, grep, cat) are, in a sense, bash commands. Some of these commands are built into bash itself; others are separate programs. For now, it doesn't make a difference which is which.
We'll end this chapter with a few recipes on getting bash. Most systems come with bash pre-installed, but a few don't. Even if your system comes with bash, it's always a good idea to know how to get and install it—new versions, with new features, are released from time to time.
If you're already running bash, and are somewhat familiar with it, you may want to go straight to . You are not likely to read this book in order, and if you dip into the middle, you should find some recipes that demonstrate what bash is really capable of. But first, the basics.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Decoding the Prompt
You'd like to know what all the punctuation on your screen means.
All command-line shells have some kind of prompt to alert you that the shell is ready to accept your input. What the prompt looks like depends on many factors including your operating system type and version, shell type and version, distribution, and how someone else may have configured it. In the Bourne family of shells, a trailing $ in the prompt generally means you are logged in as a regular user, while a trailing # means you are root. The root account is the administrator of the system, equivalent to the System account on Windows (which is even more powerful than the Administrator account), or the Supervisor account on Netware. root is all-powerful and can do anything on a typical Unix or Linux system.
Default prompts also often display the path to the directory that you are currently in; however, they usually abbreviate it. So a ~ means you are in your home directory. Some default prompts may also display your username and the name of the machine you are logged into. If that seems silly now, it won't when you're logged into five machines at once possibly under different usernames.
Here is a typical Linux prompt for a user named jp on a machine called adams, sitting in the home directory. The trailing $ indicates this is a regular user, not root.
	jp@adams:~$
Here's the prompt after changing to the /tmp directory. Notice how ~, which really meant /home/jp, has changed to /tmp.
	jp@adams:/tmp$
The shell's prompt is the thing you will see most often when you work at the command line, and there are many ways to customize it more to your liking. But for now, it's enough to know how to interpret it. Of course, your default prompt may be different, but you should be able to figure out enough to get by for now.
There are some Unix or Linux systems where the power of root may be shared, using commands like su and sudo. Or root may not even be all-powerful, if the system is running some kind of mandatory access control (MAC) system such as the NSA's SELinux.
  • , "Showing Where You Are"
  • , "Using sudo More Securely"
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Showing Where You Are
You are not sure what directory you are in, and the default prompt is not helpful.
Use the pwd built-in command, or set a more useful prompt (as in , "Customizing Your Prompt"). For example:
	bash-2.03$ pwd
	/tmp

	bash-2.03$ export PS1='[\u@\h \w]$ '
	[jp@solaris8 /tmp]$
pwd stands for print working directory and takes two options. -L displays your logical path and is the default.s displays your physical location, which may differ from your logical path if you have followed a symbolic link.
	bash-2.03$ pwd
	/tmp/dir2

	bash-2.03$ pwd -L
	/tmp/dir2

	bash-2.03$ pwd -P
	/tmp/dir1
  • , "Customizing Your Prompt"
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Finding and Running Commands
You need to find and run a particular command under bash.
Try the type, which, apropos, locate, slocate, find, and ls commands.
bash keeps a list of directories in which it should look for commands in an environment variable called $PATH. The bash built-in type command searches your environment (including aliases, keywords, functions, built-ins, and files in the $PATH) for executable commands matching its arguments and displays the type and location of any matches. It has several arguments, notably the -a flag, which causes it to print all matches instead of stopping at the first one. The which command is similar but only searches your $PATH (and csh aliases). It may vary from system to system (it's usually a csh shell script on BSD, but a binary on Linux), and usually has a -a flag like type. Use these commands when you know the name of a command and need to know exactly where it's located, or to see if it's on this computer. For example:
	$ type which
	which is hashed (/usr/bin/which)

	$ type ls
	ls is aliased to `ls -F -h'

	$ type -a ls
	ls is aliased to `ls -F -h'
	ls is /bin/ls

	$ which which
	/usr/bin/which
Almost all commands come with some form of help on how to use them. Usually there is online documentation called manpages, where "man" is short for manual. These are accessed using the man command, so man ls will give you documentation about the ls command. Many programs also have a built-in help facility, accessed by providing a "help me" argument such as -h or --help. Some programs, especially on other operating systems, will give you help if you don't give them arguments. Some Unix commands will also do that, but a great many of them will not. This is due to the way that Unix commands fit together into something called pipelines, which we'll cover later. But what if you don't know or can't remember the name of the command you need? apropos searches manpage names and descriptions for regular expressions supplied as arguments. This is incredibly useful when you don't remember the name of the command you need. This is the same as man -k.
	$ apropos music
	cms (4) - Creative Music System device driver

	$ man -k music
	cms (4) - Creative Music System device driver
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting Information About Files
You need more information about a file, such as what it is, who owns it, if it's executable, how many hard links it has, or when it was last accessed or changed.
Use the ls, stat, file, or find commands.
	$ touch /tmp/sample_file

	$ ls /tmp/sample_file
	/tmp/sample_file

	$ ls -l /tmp/sample_file
	-rw-r--r-- 1 jp	         jp            0 Dec 18 15:03 /tmp/sample_file

	$ stat /tmp/sample_file
	File: "/tmp/sample_file"
	Size: 0           Blocks: 0        IO Block: 4096   Regular File
	Device: 303h/771d Inode:  2310201    Links: 1
	Access: (0644/-rw-r--r--) Uid: (  501/      jp)   Gid: ( 501/        jp)
	Access: Sun Dec 18 15:03:35 2005
	Modify: Sun Dec 18 15:03:35 2005
	Change: Sun Dec 18 15:03:42 2005

	$ file /tmp/sample_file
	/tmp/sample_file: empty

	$ file -b /tmp/sample_file
	empty

	$ echo '#!/bin/bash -' > /tmp/sample_file

	$ file /tmp/sample_file
	/tmp/sample_file: Bourne-Again shell script text executable

	$ file -b /tmp/sample_file
	Bourne-Again shell script text executable
For much more on the find command, see all of .
The command ls shows only filenames, while -l provides more details about each file. ls has many options; consult the manpage on your system for the ones it supports. Useful options include:ls
-a
Do not hide files starting with . (dot)
-F
Show the type of file with one of these trailing type designators: /*@%=|
-l
Long listing
-L
Show information about the linked file, rather than the symbolic link itself
-Q
Quote names (GNU extension, not supported on all systems)
-r
Reverse sort order
-R
Recurse though subdirectories
-S
Sort by file size
-1
Short format but only one file per line
When using -F a slash (/) indicates a directory, an asterisk (*) means the file is executable, an at sign (@) indicates a symbolic link, a percent sign (%) shows a whiteout, an equal sign (=) is a socket, and a pipe or vertical bar (|) is a FIFO.
stat, file, and find all have many options that control the output format; see the manpages on your system for supported options. For example, these options produce output that is similar to ls -l:
	$ ls -l /tmp/sample_file
	-rw-r--r--	  1 jp         jp                14 Dec 18 15:04 /tmp/sample_file

	$ stat -c'%A %h %U %G %s %y %n' /tmp/sample_file
	-rw-r--r-- 1 jp jp 14 Sun Dec 18 15:04:12 2005 /tmp/sample_file

	$ find /tmp/ -name sample_file -printf '%m %n %u %g %t %p'
	644 1 jp jp Sun Dec 18 15:04:12 2005 /tmp/sample_file
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Showing All Hidden (dot) Files in the Current Directory
You want to see only hidden (dot) files in a directory to edit a file you forget the name of or remove obsolete files. ls -a shows all files, including normally hidden ones, but that is often too noisy, and ls -a .* doesn't do what you think it will.
Use ls-d along with whatever other criteria you have.
	ls -d .*
	ls -d .b*
	ls -d .[!.]*
Or construct your wildcard in such a way that . and .. don't match.
	$ grep -l 'PATH' ~/.[!.]*
	/home/jp/.bash_history
	/home/jp/.bash_profile
Due to the way the shell handles file wildcards, the sequence .* does not behave as you might expect or desire. The way filename expansion or globbing works is that any string containing the characters *, ?, or [ is treated as a pattern, and replaced by an alphabetically sorted list of file names matching the pattern. * matches any string, including the null string, while ? matches any single character. Characters enclosed in [] specify a list or range of characters, any of which will match. There are also various extended pattern-matching operators that we're not going to cover here (see "Pattern-Matching Characters" and "extglob Extended Pattern-Matching Operators" in ). So *.txt means any file ending in .txt, while *txt means any file ending in txt (no dot). f?o would match foo or fao but not fooo. So you'd think that .* would match any file beginning with a dot.
The problem is that .* is expanded to include . and .., which are then both displayed. Instead of getting just the dot files in the current directory, you get those files, plus all the files and directories in the current directory (.), all the files and directories in the parent directory (..), and the names and contents of any subdirectories in the current directory that start with a dot. This is very confusing, to say the least.
You can experiment with the same ls command with -d and without, then try echo.*. The echo trick simply shows you what the shell expanded your .* to. Try echo.[!.]* also.
.[!.]* is a filename expansion pattern where [] denotes a list of characters to match, but the leading ! negates the list. So we are looking for a dot, followed by any character that is
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Shell Quoting
You need a rule of thumb for using command-line quoting.
Enclose a string in single quotes unless it contains elements that you want the shell to interpolate.
Unquoted text and even text enclosed in double quotes is subject to shell expansion and substitution. Consider:
	$ echo A coffee is $5?!
	A coffee is ?!

	$ echo "A coffee is $5?!"
	-bash: !": event not found

	$ echo 'A coffee is $5?!'
	A coffee is $5?!
In the first example, $5 is treated as a variable to expand, but since it doesn't exist it is set to null. In the second example, the same is true, but we never even get there because !" is treated as a history substitution, which fails in this case because it doesn't match anything in the history. The third example works as expected.
To mix some shell expansions with some literal strings you may use the shell escape character \ or change your quoting. The exclamation point is a special case because the preceding backslash escape character is not removed. You can work around that by using single quotes or a trailing space as shown here.
	$ echo 'A coffee is $5 for' "$USER" '?!'
	A coffee is $5 for jp ?!

	$ echo "A coffee is \$5 for $USER?\!"
	A coffee is $5 for jp?\!

	$ echo "A coffee is \$5 for $USER?! "
	A coffee is $5 for jp?!
Also, you can't embed a single quote inside single quotes, even if using a backslash, since nothing (not even the backslash) is interpolated inside single quotes. But you can work around that by using double quotes with escapes, or by escaping a single quote outside of surrounding single quotes.
	# We'll get a continuation prompt since we now have unbalanced quotes
	$ echo '$USER won't pay $5 for coffee.'
	> ^C

	# WRONG
	$ echo "$USER won't pay $5 for coffee."
	jp won't pay for coffee.

	# Works
	$ echo "$USER won't pay \$5 for coffee."
	jp won't pay $5 for coffee.

	# Also works
	$ echo 'I won'\''t pay $5 for coffee.'
	I won't pay $5 for coffee.
  • for more about shell variable and the $VAR syntax
  • for more about ! and the history commands
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using or Replacing Built-ins and External Commands
You want to replace a built-in command with your own function or external command, and you need to know exactly what your script is executing (e.g., /bin/echo or the built-in echo). Or you've created a new command and it may be conflicting with an existing external or built-in command.
Use the type and which commands to see if a given command exists and whether it is built-in or external.
	# type cd
	cd is a shell builtin

	# type awk
	awk is /bin/awk

	# which cd
	/usr/bin/which: no cd in (/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/
	sbin:/usr/bin/X11:/usr/X11R6/bin:/root/bin)

	# which awk
	/bin/awk
A built-in command is just that; it is built into the shell itself, while an external command is an external file launched by the shell. The external file may be a binary, or it may be a shell script itself, and its important to understand the difference for a couple of reasons. First, when you are using a given version of a particular shell, built-ins will always be available but external programs may or may not be installed on a particular system. Second, if you give one of your own programs the same name as a built-in, you will be very confused about the results since the built-in will always take precedence (see , "Naming Your Script Test"). It is possible to use the enable command to turn built-in commands off and on, though we strongly recommend against doing so unless you are absolutely sure you understand what you are doing. enable -a will list all built-ins and their enabled or disabled status.
One problem with built-in commands is that you generally can't use a -h or --help option to get usage reminders, and if a manpage exists it's often just a pointer to the large bash manpage. That's where the help command, which is itself a built-in, comes in handy. help displays help about shell built-ins.
	# help help
	help: help [-s] [pattern ...]
	    Display helpful information about builtin commands. If PATTERN is
	    specified, gives detailed help on all commands matching PATTERN,
	    otherwise a list of the builtins is printed. The -s option
	    restricts the output for each builtin command matching PATTERN to
	    a short usage synopsis.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Determining If You Are Running Interactively
You have some code you want to run only if you are (or are not) running interactively.
Use the following case statement:
	#!/usr/bin/env bash
	# cookbook filename: interactive

	case "$-" in
	    *i*) # Code for interactive shell here
	         ;;
	    *)   # Code for non-interactive shell here
	         ;;
	esac
$- is a string listing of all the current shell option flags. It will contain i if the shell is interactive.
You may also see code like the following (this will work, but the solution above is the preferred method):
	if [ "$PS1" ]; then
	    echo This shell is interactive
	else
	    echo This shell is not interactive
	fi
  • help case
  • help set
  • , "Branching Many Ways," for more explanation of the case statement
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Setting bash As Your Default Shell
You're using a BSD system, Solaris, or some other Unix variant for which bash isn't the default shell. You're tired of starting bash explicitly all the time, and want to make bash your default shell.
First, make sure bash is installed. Try typing bash --version at a command line. If you get a version, it's installed:
	$ bash --version
	GNU bash, version 3.00.16(1)-release (i386-pc-solaris2.10)
	Copyright (C) 2004 Free Software Foundation, Inc.
If you don't see a version number, you may be missing a directory from your path. chsh -l or cat /etc/shells may give you a list of valid shells on some systems. Otherwise, ask your system administrator where bash is, or if it can be installed.
chsh -l provides a list of valid shells on Linux, but opens an editor and allows you to change settings on BSD. -l is not a valid option to chsh on Mac OS X, but just running chsh will open an editor to allow you to change settings, and chpass -s shell will change your shell.
If bash is installed, use the chsh -s command to change your default shell. For example, chsh -s /bin/bash. If for any reason that fails try chsh, passwd -e, passwd -l chpass,or usermod -s /usr/bin/bash. If you still can't change your shell ask your system administrator, who may need to edit the /etc/passwd file. On most systems, /etc/passwd will have lines of the form:
	cam:pK1Z9BCJbzCrBNrkjRUdUiTtFOh/:501:100:Cameron Newham:/home/cam:/bin/bash
	cc:kfDKDjfkeDJKJySFgJFWErrElpe/:502:100:Cheshire Cat:/home/cc:/bin/bash
As root, you can just edit the last field of the lines in the password file to the full pathname of whatever shell you choose. If your system has a vipw command, you should use it to ensure password file consistency.
Some systems will refuse to allow a login shell that is not listed in /etc/shells. If bash is not listed in that file, you will have to have your system administrator add it.
Some operating systems, notably the BSD Unixes, typically place bash in the /usr partition. You may want to think twice about changing root's shell on such systems. If the system runs into trouble while booting, and you have to work on it before
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting bash for Linux
You want to get bash for your Linux system, or you want to make sure you have the latest version.
bash is included in virtually all modern Linux distributions. To make sure you have the latest version available for your distribution, use the distribution's built-in packaging tools. You must be root or have the root password to upgrade or install applications.
Some Linux distributions (notably Debian) include bash version 2.x as plain bash and version 3.x as bash3, so you need to watch out for that. lists the default versions as of early 2007 (distributions update their repositories often, so versions might have changed from this listing).
Table 1-1: Default Linux distributions
Distribution
2.x in base install
2.x in updates
3.x in base install
3.x in updates
Debian Woody
2.05a
N/A
N/A
N/A
Debian Sarge
2.05b
3.1dfsg-8 (testing & unstable)
3.0-12(1)-release
3.00.16(1)-release
Fedora Core 1
bash-2.05b-31.i386.rpm
bash-2.05b-34.i386.rpm
N/A
N/A
Fedora Core 2
bash-2.05b-38.i386.rpm
N/A
N/A
N/A
Fedora Core3
N/A
N/A
bash-3.0-17.i386.rpm
bash-3.0-18.i386.rpm
Fedora Core 4
N/A
N/A
bash-3.0-31.i386.rpm
N/A
Fedora Core 5
N/A
N/A
bash-3.1-6.2.i386.rpm
bash-3.1-9.fc5.1.i386.rpm
Fedora Core 6
N/A
N/A
bash-3.1-16.1.i386.rpm
N/A
Knoppix 3.9 & 4.0.2
N/A
N/A
3.0-15
N/A
Mandrake 9.2
bash-2.05b-14mdk.i586.rpm
N/A
N/A
N/A
Mandrake 10.1
bash-2.05b-22mdk.i586.rpm
N/A
N/A
N/A
Mandrake 10.2
N/A
N/A
bash-3.0-2mdk.i586.rpm
N/A
Mandriva 2006.0
N/A
N/A
bash-3.0-6mdk.i586.rpm
N/A
Mandriva 2007.0
N/A
N/A
bash-3.1-7mdv2007.0.i586.rpm
N/A
OpenSUSE 10.0
N/A
N/A
3.00.16(1)-release
3.0.17(1)-release
OpenSUSE 10.1
N/A
N/A
3.1.16(1)-release
N/A
OpenSUSE 10.2
N/A
N/A
bash-3.1-55.i586.rpm
N/A
SLED 10 RC3
N/A
N/A
3.1.17(1)-release
N/A
RHEL 3.6, CentOS 3.6
bash-2.05b.0(1)
N/A
N/A
N/A
RHEL 4.4, CentOS 4.4
N/A
N/A
3.00.15(1)-release
N/A
MEPIS 3.3.1
N/A
N/A
3.0-14
N/A
Ubuntu 5.10
N/A
N/A
3.0.16(1)
N/A
Ubuntu 6.06
N/A
N/A
3.1.17(1)-release
N/A
Ubuntu 6.10
N/A
N/A
3.1.17(1)-release
N/A
For Debian and Debian-derived systems such as Knoppix, Ubuntu, and MEPIS, make sure your /etc/apt/sources.list file is pointing at an up-to-date Debian mirror; then use the graphical Synaptic, kpackage, gnome-apt
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting bash for xBSD
You want to get bash for your FreeBSD, NetBSD, or OpenBSD system, or you want to make sure you have the latest version.
To see if bash is installed, check the /etc/shells file. To install or update bash, use the pkg_add command. If you are an experienced BSD user, you may prefer using the ports collection, but we will not cover that here.
FreeBSD:
	pkg_add -vr bash
For NetBSD, browse to Application Software for NetBSD at http://netbsd.org/Documentation/software/ and locate the latest bash package for your version and architecture, then use a command such as:
	pkg_add -vu ftp://ftp.netbsd.org/pub/NetBSD/packages/pkgsrc-2005Q3/NetBSD-2.0/i386/
	All/bash-3.0pl16nb3.tgz
For OpenBSD, you use the pkg_add -vr command. You may have to adjust the FTP path for your version and architecture. Also, there may be a statically compiled version. For example: ftp://ftp.openbsd.org/pub/OpenBSD/3.8/packages/i386/bash-3.0.16p1-static.tgz.
	pkg_add -vr ftp://ftp.openbsd.org/pub/OpenBSD/3.8/packages/i386/bash-3.0.16p1.tgz
FreeBSD and OpenBSD place bash in /usr/local/bin/bash while NetBSD uses /usr/pkg/ bin/bash.
Interestingly, PC-BSD 1.2, a "rock-solid Unix operating system based on FreeBSD," comes with bash 3.1.17(0) in /usr/local/bin/bash, though the default shell is still csh.
  • , "Setting bash As Your Default Shell"
  • , "Testing Scripts in VMware"
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting bash for Mac OS X
You want to get bash for your Mac, or you want to make sure you have the latest version.
According to Chet Ramey's bash page (http://tiswww.tis.case.edu/~chet/bash/bashtop.html), Mac OS 10.2 (Jaguar) and newer ship with bash as /bin/sh. 10.4 (Tiger) has version 2.05b.0(1)-release (powerpc-apple-darwin8.0). There are also precompiled OS X packages of bash-2.05 available from many web sites. One such package is at HMUG. Bash for Darwin (the base for Mac OS X) is available from Fink or DarwinPorts.
It is also possible to build a more recent version of bash from source, but this is recommended only for experienced users.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting bash for Unix
You want to get bash for your Unix system, or you want to make sure you have the latest version.
If it's not already installed or in your operating system's program repository, check Chet Ramey's bash page for binary downloads, or build it from source (see ).
According to Chet Ramey's bash page (http://tiswww.tis.case.edu/~chet/bash/bashtop.html):
Solaris 2.x, Solaris 7, and Solaris 8 users can get a precompiled version of bash-3.0 from the Sunfreeware site. Sun ships bash-2.03 with Solaris 8 distributions, ships bash-2.05 as a supported part of Solaris 9, and ships bash-3.0 as a supported part of Solaris 10 (directly on the Solaris 10 CD).
AIX users can get precompiled versions of older releases of bash for various versions of AIX from Groupe Bull, and sources and binaries of current releases for various AIX releases from UCLA. IBM makes bash-3.0 available for AIX 5L as part of the AIX tool-box for [GNU/]Linux applications. They use RPM format; you can get RPM for AIX from there, too.
SGI users can get an installable version of bash-2.05b from the SGI Freeware page.
HP-UX users can get bash-3.0 binaries and source code from the Software Porting and Archive Center for HP-UX.
Tru64 Unix users can get sources and binaries for bash-2.05b from the HP/Compaq Tru64 Unix Open Source Software Collection.
  • , "Setting bash As Your Default Shell"
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting bash for Windows
You want to get bash for your Windows system, or you want to make sure you have the latest version.
Use Cygwin.
Download http://www.cygwin.com/setup.exe and run it. Follow the prompts and choose the packages to install, including bash, which is located in the shells category and is selected by default. As of early 2007, bash-3.1-6 and 3.2.9-11 are available.
Once Cygwin is installed, you will have to configure it. See the User Guide at http://cygwin.com/cygwin-ug-net.
From the Cygwin site:
What Is Cygwin
Cygwin is a Linux-like environment for Windows. It consists of two parts:
  • A DLL (cygwin1.dll), which acts as a Linux API emulation layer providing substantial Linux API functionality.
  • A collection of tools, which provide Linux look and feel.
    The Cygwin DLL works with all non-beta, non "release candidate," x86 32-bit versions of Windows since Windows 95, with the exception of Windows CE.
    What Isn't Cygwin
  • Cygwin is not a way to run native Linux apps on Windows. You have to rebuild your application from source if you want to get it running on Windows.
  • Cygwin is not a way to magically make native Windows apps aware of Unix functionality (e.g., signals, ptys). Again, you need to build your apps from source if you want to take advantage of Cygwin functionality.
Cygwin is a true Unix-like environment running on top of Windows. It is an excellent tool, but sometimes it might be overkill. For Windows native binaries of the GNU Text Utils (not including bash), see http://unxutils.sourceforge.net/.
Microsoft Services for Unix (http://www.microsoft.com/windowsserversystem/sfu/default.mspx) may also be of interest, but note that it is not under active development anymore, though it will be supported until at least 2011 (http://www.eweek.com/article2/0,1895,1855274,00.asp).
For powerful character-based and GUI command-line shells with a more consistent interface, but a DOS/Windows flavor, see http://jpsoft.com/. None of the authors are affiliated with this company, but one is a long-time satisfied user.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting bash Without Getting bash
You want to try out a shell or a shell script on a system you don't have the time or the resources to build or buy.
Or, you feel like reading a Zen-like recipe just about now.
Get a free or almost free shell account from HP, Polar Home, or another vendor.
HP maintains a free "test drive" program that provides free shell accounts on many operating systems on various HP hardware. See http://www.testdrive.hp.com/ for details.
Polar Home provides many free services and almost free shell accounts. According to their web site:
polarhome.com is non commercial, educational effort for popularization of shell enabled operating systems and Internet services, offering shell accounts, mail and other online services on all available systems (currently on Linux, OpenVMS, Solaris, AIX, QNX, IRIX, HP-UX, Tru64, FreeBSD, OpenBSD, NetBSD and OPENSTEP).
[…]
Note: this site is continuously under construction and running on slow lines and low capacity servers that have been retired, therefore as a non commercial site user/visitor, nobody should have too high expectations in any meaning of the word. Even if polarhome.com does all to provide services on professional level, users should not expect more than "AS-IS".
polarhome.com is a distributed site, but more than 90% of polarhome realm is located in Stockholm, Sweden.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Learning More About bash Documentation
You'd like to read more about bash but don't know where to start.
Well you're reading this book, which is a great place to start! The other O'Reilly books about bash and shell scripting are: Learning the bash Shell by Cameron Newham (O'Reilly) and Classic Shell Scripting by Nelson H.F. Beebe and Arnold Robbins (O'Reilly).
Unfortunately, the official bash documentation has not been easily accessible online—until now! Previously, you had to download several different tarballs, locate all the files that contain documentation, and then decipher the file names to find what you wanted. Now, our companion web site (http://www.bashcookbook.com/) has done all this work for you and provides the official bash reference documentation online so it's easy to refer to. Check it out, and refer others to it as needed.

Section 1.16.2.1: Official documentation

The official bash FAQ is at: ftp://ftp.cwru.edu/pub/bash/FAQ. See especially "H2) What kind of bash documentation is there?" The official reference guide is also strongly recommended; see below for details.
Chet Ramey's (the current bash maintainer) bash page (called bashtop) contains a ton of very useful information (http://tiswww.tis.case.edu/~chet/bash/bashtop.html). Chet also maintains the following (listed in bashtop):
README
NEWS
A file tersely listing the notable changes between the current and previous versions: http://tiswww.tis.case.edu/chet/bash/NEWS
CHANGES
A complete bash change history: http://tiswww.tis.case.edu/chet/bash/CHANGES
INSTALL
NOTES
Platform-specific configuration and operation notes: http://tiswww.tis.case.edu/chet/bash/NOTES
COMPAT
Compatibility issues between bash3 and bash1: http://tiswww.tis.case.edu/~chet/bash/COMPAT
The latest bash source code and documentation are always available at: http://ftp.gnu.org/gnu/bash/.
We highly recommend downloading both the source and the documentation even if you are using prepackaged binaries. Here is a brief list of the documentation. See for an index of the included examples and source code. See the source tarball's
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Standard Output
No software is worth anything if there is no output of some sort. But I/O (Input/ Output) has long been one of the nastier areas of computing. If you're ancient, you remember the days most of the work involved in running a program was setting up the program's input and output. Some of the problems have gone away; for example, you no longer need to get operators to mount tapes on a tape drive (not on any laptop or desktop system that I've seen). But many of the problems are still with us.
One problem is that there are many different types of output. Writing something on the screen is different from writing something in a file—at least, it sure seems different. Writing something in a file seems different from writing it on a tape, or in flash memory, or on some other kind of device. And what if you want the output from one program to go directly into another program? Should software developers be tasked with writing code to handle all sorts of output devices, even ones that haven't been invented yet? That's certainly inconvenient. Should users have to know how to connect the programs they want to run to different kinds of devices? That's not a very good idea, either.
One of the most important ideas behind the Unix operating system was that everything looked like a file (an ordered sequence of bytes). The operating system was responsible for this magic. It didn't matter whether you were writing to a file on the disk, the terminal, a tape drive, a memory stick, or something else; your program only needed to know how to write to a file, and the operating system would take it from there. That approach greatly simplified the problem. The next question was, simply, "which file?" How does a program know whether to write to the file that represents a terminal window, a file on the disk, or some other kind of file? Simple: that's something that can be left to the shell.
When you run a program, you still have to connect it to output files and input files (which we'll see in the next chapter). That task doesn't go away. But the shell makes it trivially easy. A command as simple as:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Writing Output to the Terminal/Window
You want some simple output from your shell commands.
Use the echo built-in command. All the parameters on the command line are printed to the screen. For example:
	echo Please wait.
produces
	Please wait.
as we see in this simple session where we typed the command at the bash prompt (the $ character):
	$ echo Please wait.
	Please wait.
	$
The echo command is one of the most simple of all bash commands. It prints the arguments of the command line to the screen. But there are a few points to keep in mind. First, the shell is parsing the arguments on the echo command line (like it does for every other command line). This means that it does all its substitutions, wildcard matching, and other things before handing the arguments off to the echo command. Second, since they are parsed as arguments, the spacing between arguments is ignored. For example:
	$ echo this    was     very    widely    spaced
	this was very widely spaced
	$
Normally the fact that the shell is very forgiving about white space between arguments is a helpful feature. Here, with echo, it's a bit disconcerting.
  • help echo
  • help printf
  • , "Writing Output with More Formatting Control"
  • , "Using echo Portably"
  • , "Forgetting to Set Execute Permissions"
  • "echo Options and Escape Sequences" in
  • "printf" in
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Writing Output but Preserving Spacing
You want the output to preserve your spacing.
Enclose the string in quotes. The previous example, but with quotes added, will preserve our spacing.
	$ echo "this was   very   widely    spaced"
	this    was  very  widely    spaced
	$
or:
	$ echo 'this  was  very   widely   spaced'
	this    was   very  widely  spaced
	$
Since the words are enclosed in quotes, they form a single argument to the echo command. That argument is a string and the shell doesn't need to interfere with the contents of the string. In fact, by using the single quotes ('') the shell is told explicitly not to interfere with the string at all. If you use double quotes ("), some shell substitutions will take place (variable and tilde expansions and command substitutions), but since we have none in this example, the shell has nothing to change. When in doubt, use the single quotes.
  • help echo
  • help printf
  • for more information about substitution
  • , "Writing Output with More Formatting Control"
  • , "Using echo Portably"
  • , "Seeing Odd Behavior from printf"
  • "echo Options and Escape Sequences" in
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Writing Output with More Formatting Control
You want more control over the formatting and placement of output.
Use the printf built-in command.
For example:
	$ printf '%s = %d\n' Lines $LINES
	Lines = 24
	$
or:
	$ printf '%-10.10s = %4.2f\n' 'GigaHerz' 1.92735
	GigaHerz   = 1.93
	$
The printf built-in command behaves like the C language library call, where the first argument is the format control string and the successive arguments are formatted according to the format specifications (%).
The numbers between the % and the format type (s or f in our example) provide additional formatting details. For the floating-point type (f), the first number (4 in the 4.2 specifier) is the width of the entire field. The second number (2) is how many digits should be printed to the right of the decimal point. Note that it rounds the answer.
For a string, the first digit is the maximum field width, and the second is the minimum field width. The string will be truncated (if longer than max) or blank padded (if less than min) as needed. When the max and min specifiers are the same, then the string is guaranteed to be that length. The negative sign on the specifier means to left align the string (within its field width). Without the minus sign, the string would right justify, thus:
	$ printf '%10.10s = %4.2f\n' 'GigaHerz' 1.92735
	GigaHerz =   1.93
	$
The string argument can either be quoted or unquoted. Use quotes if you need to preserve embedded spacing (there were no spaces needed in our one-word strings), or if you need to escape the special meaning of any special characters in the string (again, our example had none). It's a good idea to be in the habit of quoting any string that you pass to printf, so that you don't forget the quotes when you need them.
  • help printf
  • Learning the bash Shell, Cameron Newham (O'Reilly), , or any C refer-ence on its printf function
  • , "Using echo Portably"
  • , "Seeing Odd Behavior from printf"
  • "printf" in
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Writing Output Without the Newline