As mentioned earlier,
bash is Mac OS X’s default Unix shell. Apple made the switch from
bash because of its support for Unicode text, something that’s very important in the international market. Another logical reason for switching to
bash is that it is the default shell for most Linux distributions and is easier to script with than
bash is now the default shell, this book focuses on its use, with an occasional nod to the other shells where appropriate.
The default configuration of
bash is perfectly adequate for casual usage, but you’ll inevitably want to configure it to your own liking. This section takes a look at the various configuration files for
bash, its environment variables
, how to set
up command aliases, and how to use
bash’s history to your advantage. You’ll also learn a bit about redirecting output between commands and into files, as well as some basic shell loops.
Every program on the system runs in an
environment. The environment consists of a set of name-value pairs, known as
environment variables, which communicate a variety of configuration settings to a program. For example, the shell uses the
PATH environment variable to find a program to execute in response to a command. To get an idea of what kinds of data are stored in environment variables, execute the
set command, as shown in Example 4-5.
Example 4-5. Examining environment variables with set
setBASH=/bin/bash BASH_VERSINFO=(="2" ="05b" ="0" ="1" ="release" ="powerpc-apple-darwin8.0") BASH_VERSION='2.05b.0(1)-release' COLUMNS=80 DIRSTACK=() EUID=501 GROUPS=() HISTFILE=/Users/jldera/.bash_history HISTFILESIZE=500 HISTSIZE=500 HOME=/Users/jldera HOSTNAME=ronin.local HOSTTYPE=powerpc ...
When you execute the
set command, you’ll see quite a bit of output—probably around 40 lines. Some of the environment variables may make sense when you first look at them, and some won’t. Table 4-6 lists some of the environment variables you are likely to use on occasion.
Table 4-6. Commonly used bash environment variables
Location of the
Number of columns to use in Terminal view
List of directories used by the
Various groups with which the user is associated
File containing the shell history
Home directory for the user
Name of the system on which the shell is running
Number of lines currently being used by the shell
List of directories the shell uses to resolve commands
String used as the primary prompt
String used as the secondary prompt
Shell program being used
Options in effect for the shell
Type of terminal that the shell is displaying its content to
User ID of the currently logged-in user
Username of the currently logged-in user
Previously executed command
To see the value of a single environment variable such as
PATH, you can use the
command, as shown in Example 4-6.
The dollar sign in front of
PATH means you are referring to an environment variable. If you had just entered
echo PATH, the shell would return
PATH, as shown in Example 4-7.
To set or change an environment variable for the lifetime of the shell, use the
command. For example, to change the
PATH variable so that you can run your own commands in
~/bin, you could use the following command:
This sets the
PATH variable to the currently existing
PATH with the
~/bin directory appended to it. An important thing to remember here is that you need to use a colon (
:) as a delimiter between command paths
. These commands will last for the lifetime of the current shell, which is as long as that Terminal window is open. To add these paths to the shell permanently, you’ll have to edit one of
bash’s configuration files
, described next.
bash first starts, it looks for
run command files. Commonly called
rc files, Unix apps use these files to store basic configuration data that is used as the program loads. As a matter of fact, there are some special
rc files in the
/etc folder that are involved with the initial setup and loading of Mac OS X itself. You can learn some more about them in Chapter 5.
bash shell first looks at the
/etc/profile file for its initial state. This is a system-wide set of default settings that are superseded by any other files subsequently loaded by
bash. Next, three files in the Home directory, if they exist, are used to configure
Contains environment variables and commands that are read and executed every time you create a new Terminal window and a shell is created for it, or when you SSH into your machine and are presented with a prompt. This allows you to customize the shell to your liking. If
bash doesn’t find this file, it looks for
.profile respectively to fill in for it.
Contains environment variables and commands that are read and executed only when you create a subshell by typing
bash in an already running shell.
Contains commands that are read and executed when you log out of a shell. You could use this to clean up files before you log out.
By default, these files don’t exist as part of a user’s Home directory until you create them. The most useful of these three files is
.bash_profile, which is used to customize the shell. For example, if you wanted to permanently modify the
PATH that the shell uses to resolve commands, you could create a
.bash_profile file in your Home directory and add the following line:
This causes the
PATH environment variable to be set to the given string each time you open a new Terminal window. Because
.bash_profile is only read when the shell is created, any changes you make to it won’t take effect until you start the next shell. If you don’t want to close your shell and start a new one, you can use the
source command to load the contents of the
In addition to searching the
PATH for commands, the
bash shell lets you define a set of aliases
. Aliases are commonly used to create a shorter command name for long command strings so that they’re a bit more manageable or to rename commonly used commands. It’s important to note that these are not the same aliases as those defined in the Finder. Finder aliases are closer to the Unix concept of a symbolic link. It’s a shortcut to a file instead of a shortcut for a command.
To define an
alias for a command, use the following syntax:
name is the name of the
command alias you are defining, and
command is the command that’s actually executed by the shell when you invoke the alias. One common use of aliases is to accommodate fat-fingering of commands. For example, if you are always typing
sl instead of
ls, you could define the following alias so that you don’t get scolded by the shell again:
Another use for aliases is to create a simple command for a longer one. For example, if you are often changing directories to somewhere deep in the hierarchy, you can set up an alias that will allow you to go there quickly:
alias fdocs="cd ~/Documents/Corporate/Master/Forecasts"
Notice the use of quotes around the command. This is required when a command consists of more than one word.
Yet another use for aliases is to redefine a command to add some default options. For example, if you’re constantly forgetting about the hidden dot files on your machine, you can redefine the way the shell handles the
alias ls="ls -a"
As another example, if you’re still getting used to the fact that the shell doesn’t make use of the Trash can, you can make the
rm command ask you to confirm file deletions by using its
alias rm="rm -i"
To get a list of all the aliases currently defined, use the
alias command by itself, as shown in Example 4-8.
Example 4-8. Examining the currently defined shell aliases
aliasalias sl=ls alias fdocs="cd ~/Documents/Corporate/Master/Forecasts"
You can even make aliases to GUI applications. For example, if you wanted to create a quick shortcut to open the Safari browser while on the command line, you could define the following alias:
alias safari="open -a Safari"
With this alias in place, to launch Safari, you simply need to type
safari into the command line. And remember, to make an alias permanent, you’ll need to create a
.bash_profile file and place the alias into it or edit your existing
.bash_profile file and then
source it so the change takes effect.
bash runs, it keeps a history
of the commands that you’ve executed. This feature is quite handy as it lets you look at and reuse commands that you’ve previously entered. Where the shell’s history is particularly useful is when you need to invoke a command that has a lengthy set of parameters that you can’t remember.
The simplest way to use the history is to use the up and down arrows on your keyboard. This will step back and forth through the commands that you’ve executed and display each in turn at the prompt. To get more out of the history, you can use the
history command, which displays a list of previously executed commands. Example 4-9 shows some output from
The commands are listed in the order in which they were executed. To reuse a particular command, type
! (exclamation point; also called “bang” by Unix geeks), followed by the number of the command you want to reuse. Example 4-10 shows how to use this command.
Example 4-10. Using a command from the history
!2ls Adobe SVG 3.0 Installer Log Music Desktop Pictures Documents Public Library Sites Movies Work
Note that the shell tells you which command is running as it runs the command. This is useful because you can tell what arguments are being used. Another way to navigate the history list is to use the first few letters of the command instead of the command number. Example 4-11 shows how to quickly execute the last command that started with an o character.
Whenever you exit
bash, it writes its history to the
~/.bash_history file. Likewise, whenever you start
bash, it populates its history with the contents of the
~/.bash_history file. This allows you to quit and restart your shell and still have your history available to you. By default, the history file is set to retain up to the last 500 commands. To change this value, set the
HISTFILESIZE environment variable to the number of lines that you want to keep. For example, to change it to remember 1,000 commands instead of 500, you would use the following:
Once again, if you’d like to make this change permanent, you’ll have to add it to your
If you’ve been using the shell for a while, the
history command might have so many entries to display that they scroll by too quickly for you to read them. Earlier in the chapter, you learned about the
more command. It might have occurred to you that this would be a perfect opportunity to use
more to paginate the
history command’s output. However, it may not have been immediately obvious how to do so.
This is where one of the most powerful features of the Unix shell comes into play. The shell allows you to redirect the output from one command and pass it along to another command. It also enables you to redirect a command’s output to a file for later perusal. For example, if the
history command’s output is scrolling too quickly for you, you could redirect its output to the
more command as follows:
history | more
The pipe (|) character is used for passing the data between commands. For saving the output to a file, you’d use the greater than character (>). So if you wanted to save a directory listing of your
/Applications folder to a file on your Desktop, use the command:
ls -l /Applications > ~/Desktop/DirectoryListing.txt
You can even append output from a command to the end of a file by using two greater than symbols (>>). If you want to add the directory listing of your
/Applications/Utilities folder to the file on your desktop:
ls -l /Applications/Utilities >> ~/Desktop/DirectoryListing.txt
For some fun with redirecting data between commands, try using the
ls command to send a directory listing to the
say command. Just make sure your speakers are on to hear the results.
Another powerful feature the shell gives you is the ability to loop through commands. This will come into play more in Chapter 13 when shell scripts are covered, but for now, here’s a basic example of a loop. Let’s say that you have several text files on your Desktop that you want the
say command to read aloud to you. After reading the discussion of wildcards earlier in the chapter, you might think the following command would work:
However, executing that command will make
say merely speak the files’ names, not read the files’ contents to you. To have each file read aloud, you need to supply each file’s name to the
say command, using only one file each time you issue the command. This can quickly become tedious if you have several files you want to have read aloud.
If you enter the shell commands shown in Example 4-12, you can make the shell do all of that work for you:
The first line of this loop starts with the
for command, which tells
bash that we’re defining a loop. The next value,
i, is a temporary variable to hold a single file’s name. The
in portion tells
for that the part that follows,
$(ls ~/Desktop/*.txt), is where it should look for the values to place in
$() convention is used to have the shell place the output of one command (in this case,
ls ~/Desktop/*.txt) into another, but isn’t quite the same as redirecting the output using a pipe.
do line indicates to the shell that the commands that follow are the contents of the loop. The loop is closed with a simple
done command. When executed, the shell will use the
ls command to find all files in
~/Desktop that end in
.txt. The shell will then take the first result, store it in the variable
i, and process the commands between
done. Once the commands have been executed, the shell takes the next value from the directory listing results, places it in the
i variable, and then loops through the commands again.