Linux

Beginning with BASH, part 1: The basics

Vincent Danen introduces you to the Bourne Again Shell (BASH) and shows you how it can simplify your life.

Shells—the heart of your Linux operating system—are command-language interpreters that tell Linux what to do. They also serve as an interface to all the utilities and applications on your system.

BASH is perhaps one of the easiest-to-use and most popular Linux shells. Although a number of other shells are available for Linux, BASH is an excellent place to start for people who are new to Linux. The most common shells on Linux and UNIX systems are the Bourne Shell (sh), the C Shell (csh), and the Korn Shell (ksh). BASH is an extension of the Bourne Shell, and it stands for Bourne Again Shell.

The benefits of BASH over the original Bourne Shell are many, but the biggest advantage relates to how BASH handles user input. As I’ll show you in this Daily Drill Down, BASH provides several features that make entering commands a lot easier than with the Bourne Shell. Due to this ease of use, BASH is often favored over sh. However, BASH is completely backwards compatible with sh. Long-time users of sh will be familiar with how BASH works and can benefit from the many extra features.

Command-line completion
One of the nicest features of BASH is its command-line completion feature. If you want to change to a directory called games, you normally type cd games. With BASH, you simply type cd g; BASH knows which directory you want, and it will change to the games directory automatically. However, let’s suppose that you have a directory called games and another called graphics. In that case, BASH won’t know which directory you want—you have to use the command cd ga for BASH to know which directory you mean.

You can test BASH in this way, too. BASH can complete and display the command for you if you press the [Tab] key. For example, typing cd ga and pressing [Tab] displays cd games on the command line. In order for BASH to run the command, you must press [Enter]. Doing so verifies that the command with which BASH comes up is really the command that you intended to run. If BASH can't complete your command, it will beep at you, alerting you to the fact that it needs more information to complete the command. BASH will provide a list of possibilities that match the letters you’ve typed, and you can make the appropriate selection.

I can't think of a better use for this feature than for viewing program documentation. More often than not, documentation is placed into the /usr/doc directory tree—in a subdirectory with the same name as the program and version. Say that you want to look at the documentation for xmms, the X MultiMedia System. Without knowing the version number, you can type cd /usr/doc/xmms. BASH will change to the /usr/doc/xmms-0.9.1 directory, where the documentation for the currently installed version of xmms resides.

Command history
Another nice feature of BASH is the command history. BASH will keep track of a certain number of previously issued commands in the ~/.bash_history file (which is customizable via the HISTFILE bash variable). The number of commands in the history is likewise customizable via the HISTSIZE variable.

When you first enter the shell, the history list is initialized by the defined history file (~/.bash_history). The history list is kept in memory until you exit the shell, at which point the list is written to the history file, overwriting its current contents. Even when you log in initially, you have a history of what you did during your last login session.

You can access the commands that are stored in the history file by using the up and down arrow keys to move to a previous or next previously issued command, similar to the DOSKEY utility. Once you’ve selected a command, you can edit it to suit your needs by inserting or deleting characters. (Use the right and left arrows to move within the command.) BASH provides the means to edit commands on the command line, similar to commands used in the emacs and vi editors. Instead of typing a long command, you can recall a previous command that’s similar to the one you wish to run now, and you can modify it.

Another method of accessing the command history is to use the history and fc commands. The history command, by default, lists the lines that are contained in the history file, and it can be limited to x number of lines. For example, issuing the command history 10 displays the last ten lines in the history file. You also can use the history command to modify the contents of the history file. In this form, history has the following command-line syntax:
history [-r|w|a|n] [filename]

The command-line options for history are quite simple. The -r option tells history to read the contents of the history file and use them as the current history list. The -w option tells history to write the current history list to the history file and overwrite its current contents. The -a option tells history to append the current history list to the history file, and the -n option causes the lines that are in the history file to be read into the current history list. Finally, the [filename] command option can be used to specify a filename other than the one that’s used by the HISTFILE variable.

You can use the fc (fix command) command to edit the command history directly. The fc command has the following command-line syntax:
fc [-e editor] [-n] [-l] [-r] [first] [last]

All of the options within braces are optional. The [first] and [last] options are used to take a range of commands out of the history list; you can specify the number of the command or a string to match. The -n command is used to suppress command numbers when the history command lists the command history. The -l command lists the matched commands to the screen. Finally, the -r command lists the commands in reverse order. In all cases, except when you use the -l command, the results of the fc command are loaded into the text editor.

The text editor that fc uses can be specified on the command line with the -e command. However, if that option is not specified, fc will take the editor name from the FCEDIT variable. If that variable doesn't exist, fc will use the EDITOR variable. Finally, if that variable doesn't exist, fc will use vi by default.

Wildcards
Like any other shell on any operating system, BASH also supports wildcards. The supported wildcard types include the following:
  • * matches any character or any number of characters
  • ? matches any single character
  • [...] matches any single character contained within the brackets
  • {...} matches a specified range of characters contained within the curly brackets

The * wildcard works like you’d expect because it’s universally used by nearly every shell for every operating system in existence. The ? wildcard is similar to the * wildcard, except that it matches only a single character. The [...] wildcard allows you to specify which characters (or range of characters) you want matched. The {...} wildcard lets you specify a more detailed range of characters to match. You can match single characters or multiple characters if you separate them with commas. For example, the wildcard file{ab,123,s,test}23 would match fileab23, file12323, files23, and filetest23.

Suppose that you have the files test1.doc, test2.doc, test3.doc, and my.doc in the directory. The following illustrates how the various wildcards work:
  • ls *.doc displays test1.doc, test2.doc, test3.doc, and my.doc.
  • ls test?.doc displays test1.doc, test2.doc, and test3.doc.
  • ls test[12].doc displays test1.doc and test2.doc.
  • ls test[1-3].doc displays test1.doc, test2.doc, and test3.doc.
  • ls test{1,3}.doc displays test1.doc and test3.doc.

Aliases
Those of you who are familiar with JPSoft's shell replacements for DOS, OS/2, and Windows (4DOS, 4OS2, and 4NT, respectively) will appreciate the aliases feature in BASH. Aliases are designed to save you some typing and make life simpler.

For example, suppose that you like different views with the ls command but don't always want to specify the options on the command line (or perhaps you can't remember them). You may want to do something like this:
alias lsa='ls -alF'

This command gives you a long directory listing that shows all filenames and adds a slash to directory names for easier viewing. If you're a newcomer to Linux from a DOS-like operating system (such as MS-DOS, Windows, or OS/2), you may want to make things easier for yourself by defining a number of aliases like this:
  • alias dir='ls'
  • alias copy='cp'
  • alias rename='mv'
  • alias md='mkdir'
  • alias rd='rmdir'

To turn off an alias, just type unalias [alias]. For example, to turn off the dir alias, type unalias dir. To load aliases each time that you enter the shell, enter the commands in the ~/.bash_profile or ~/.profile file, depending on which distribution you use. The ~/.bash_profile file contains a number of commands that set the environment for the BASH shell, not just aliases, and it’s initialized every time that you start a new shell.

Pipes
Pipes (or pipelines) are a way to string a number of commands together. The output from the first command is "piped" into the second command as input, the output from the second command is "piped" into the third command as input, and so on. The output from the last command is printed to the screen (or redirected to a file). In order to pipe commands, you must use the pipe (vertical bar or "|" character). It tells BASH where one command ends and the next begins. There’s no limit to the number of pipes that you can use.

Suppose that you’re searching for the names of installed RPM packages. You’re looking for all the packages that have to do with MySQL, and you need to know all the names of the packages. You could accomplish this task with the following command:
rpm -qa | grep MySQL

This command tells RPM to query the local database. The command’s output (the list of all the installed RPM packages) is piped into the grep command, which searches for a string of "MySQL." (Case is important, of course.) The output of this command might be
MySQL-client-3.22.25-4mdk
MySQL-3.22.25-4mdk
MySQL-bench-3.22.25-4mdk

There are literally hundreds of uses for pipes, ranging from simple tasks (like the one above) to extremely convoluted tasks.

Redirection
BASH, like every other shell, supports redirection for commands. You can redirect the output from a command to a file or device other than the local console. Likewise, you can use a file or device to provide input to a command. There are a number of uses for redirection—more for output redirection than for input redirection—but you’ll encounter many situations where either method can be used.

To redirect the output from a command to a new file (or overwrite an existing file), use the > symbol. For instance, if you want the output from the df program (which shows you how much free space you have on each mounted device), you might use
df > ~/df.txt

This command will redirect the output from the df command to the file df.txt, which is located in your home directory. To redirect the output from a command to a new file (or append to the end of an existing file), use the > symbol twice (that is, >>).

The redirection point doesn’t necessarily have to be a file. You can redirect the output of a program to another virtual console, a printer, or any other device. Simply use the device name, as opposed to a filename. For example, to redirect the output of df to the second virtual console, type
df > /dev/tty2

You may find a use for input redirection at some point. Input redirection is not used nearly as much as output redirection, but it’s definitely helpful. Let's say that you have the file article.txt and you want to obtain the number of words in the file. You can use something as simple as wc article.txt, or you could use input redirection like this:
wc < article.txt

Some programs request input from the console by default and don’t let you specify a filename on the command line. Fortunately, wc isn’t one of these programs. Input redirection is helpful when you’re dealing with programs of this nature.

Suspending processes
Another feature of BASH is its ability to suspend currently running processes, otherwise known as Job Control. With process suspension, you can suspend a command that you executed on the command line, and you can resume it later.

Pressing [Ctrl][Z] suspends the currently running process. You can use two commands, bg and fg, to resume the process in the background or the foreground, as required.

More often than not, these commands become important when users start a program in the foreground but meant to start it in the background. When a command is started in the foreground, it locks the console until the process is complete. Usually, programs execute quite quickly, and it isn't a problem. However, some programs, like system daemons, are meant to be started in the background and remain there. Or perhaps you started a process that will take more than a few minutes to finish, and you want the console back. A few options are open to you at that point. You can open a new xterm (in X) or switch to a free virtual console, or you can suspend the process and restart it in the background. To suspend and restart a process in the background, issue
CTRL-Z
bg


at the console. The first command suspends the currently running program, and the second restarts it in the background.

Conclusion
As you can see, BASH offers a number of enhancements over its predecessor, the Bourne Shell. However easy BASH may be to use, keep in mind that it’s an extremely powerful shell that you can customize to suit your own personal needs. It also can be used to write shell scripts, little programs that run often-used commands (or a series of commands). Shell scripts are similar to DOS batch files.

In part 2 of this series, I’ll show you how to customize BASH, and I’ll look at some of the commands and variables that BASH uses and looks for. I’ll also begin to discuss shell scripting (sometimes called shell programming) in BASH.

Vincent Danen, a native Canadian in Edmonton, Alberta has been computing since the age of 10, and he has been using Linux for nearly two years. Prior to that, he used OS/2 exclusively for approximately four years. Vincent is a firm believer in the philosophy behind the Linux "revolution,” and he attempts to contribute to the Linux cause in as many ways as possible—from his FreezerBurn Web site to building and submitting custom RPMs for the Linux Mandrake project. Vincent also has obtained his Linux Administrator certification from Brainbench . He hopes to tackle the RHCE once it can be taken in Canada.

About

Vincent Danen works on the Red Hat Security Response Team and lives in Canada. He has been writing about and developing on Linux for over 10 years and is a veteran Mac user.

0 comments

Editor's Picks