Bash Scripting Introduction HOWTO
This HOWTO helps you write basic Bash shell scripts. This HOWTO assumes that you know nothing about shell scripting, but it assumes you have used Bash or the Bourne shell interactively. You do not have to be a programmer to benefit from this HOWTO. This is not an advanced shell scripting HOWTO. If you want to read an advanced document on this topic, see The Advanced Bash-Scripting Guide.
The Bourne Again Shell (Bash) is the primary shell of the GNU system. It is compatible with the Bourne shell, which is one of the oldest UNIX shells, but it has many enhancements that make it superior to the Bourne shell. A Bash script is a human-readable file containing commands that are executed by Bash. This HOWTO is an introduction to writing Bash scripts.
This HOWTO is written for anyone who wants to begin writing Bash scripts but who has no prior scripting experience. You do not have to be a programmer to benefit from this HOWTO, but you need to have some experience using Linux (or any UNIX system) from an interactive shell, preferably Bash or the Bourne shell. If you are a C shell user who has never used a Bourne-like shell, some of the Bash commands may appear strange, but this HOWTO should still be valuable to you.
 Credits and Contributors
This document is based on the LDP howto written by Mike G. The following people contributed to this document in one form or another:
- Nathan Hurst
- Jon Abbott
- Felix Hudson
- Kees van den Broek
- Andreas Beck
See this page's "history" tab for more contributors.
This document, Introduction to Bash Scripting HOWTO, is copyrighted (C) 2002 by Francis Litterio. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
 Getting Started
 What You Should Already Know
This HOWTO assumes you know the following things about using Bash interactively.
- You understand the purpose of the Bash startup files .bash_profile and .bashrc in your home directory, even if you have not edited them yourself. For more information on Bash startup files refer to the man page for Bash on your system, which is usually found by running the command "man bash" or "man bash | less" for a more navigable man page on Solaris.
- You understand the purpose of the environment variables HOME and PATH.
- You understand the purpose of basic shell metacharacters, such as "*", "?", and "~".
- You understand how to run commands in the background by appending a "&" to the end of a command.
 What and Where is Bash?
Bash is a shell, which is a program that reads commands and executes them. Sometimes, the commands that Bash reads come directly from the keyboard as you type them. When this happens, we say that Bash is an interactive shell. If you've ever logged into a UNIX system, then you've used an interactive shell. Bash is the default interactive shell of the GNU/Linux system (and you might also find it installed on commercial UNIX systems). Sometimes, the commands that Bash reads come from a file called a shell script. When this happens, we say that Bash is a non-interactive shell. In this case, Bash reads each line of the script file from top to bottom, executing each command as if it had been typed on the keyboard.
Where is the Bash shell? On GNU/Linux systems, you'll always find Bash in /bin/bash. On commerical UNIX systems, such as Solaris or HP-UX, you might find it in the same place, or it might be in /usr/local/bin/bash. You rarely need to run Bash directly, but you need to know where Bash is located on your system so that you can write the very first line of your Bash scripts correctly.
Often, you can find where Bash is located on a UNIX system by typing "which bash" or "type bash" to your interactive shell. If that doesn't work, try this find command (but beware that it may take a while to complete):
find / -type f -name bash 2>/dev/null
If you are running the C shell (csh), you might find Bash by typing "whereis bash".
If that doesn't work, ask your system administrator or local guru for help. It's possible that you do not have Bash installed on your system. If this is the case, you'll have to download the source code for Bash, build it, and install it. If you've never done those things, ask your system administrator or local guru for help. It's not hard to do.
 Writing a Simple Bash Script
Let's start with a simple Bash script and work up to more complex ones later. Just about the simplest program you can write in any programming language is a Hello World program, which is a program that simply outputs the text "Hello world". Example 1 shows a Bash script to do that.
Example 1. A Simple Hello World Script
#!/bin/bash echo Hello world
Example 1 shows a very simple two-line Bash script. Create this script by typing those two lines into a file using your favorite text editor. The name of the file can be anything you choose, but you should not name the file test, because there is a built-in test command in almost every shell, and it's too easy to accidentally run the built-in test command instead of your own script. I suggest that you name this script hello.
Be careful to type the script exactly as you see it in Example 1. If you misspell a word or mistype the first line, the script may not work. One common mistake is to put a space somewhere on the first line. There should be no spaces anywhere on the first line. Another common mistake is to put one or more blank lines above the line containing "#!/bin/bash". That line must be the very first line of the script. 2.4. Running the Hello World Script
Once you've created your Hello World script, you can execute it in a variety of ways. Let's assume that you named the script hello, and it exists in your current working directory. Example 2 shows how to execute the script. In this example, the interactive shell's prompt is shown as "bash$". Your shell's prompt might look different, but that's OK.
Example 2. How to Run a Bash Script
bash$ bash hello Hello world
When you type "bash hello" as shown in Example 2, if you get an error message that says "command not found" (or something similar) then either you don't have Bash installed on your system or it is installed in a directory that is not listed in the value of your PATH environment variable. If you get an error message that says "No such file or directory", then your current working directory is probably not the one containing the script you just created.
The command "bash hello" starts a non-interactive Bash shell and passes it one argument: the name of the file containing the script to execute. While the script is running, there are actually two shells running! One is the interactive Bash shell which displays the "bash$" prompt and executes the command "bash hello". The other is the non-interactive Bash shell that you manually started to execute the script. The interactive shell isn't doing anything while the script is running — it's merely waiting for the non-interactive shell to terminate. In Example 2, the interactive shell is Bash, but you don't have to use Bash as your interactive shell to run a Bash script. The command shown in Example 2 will work no matter which interactive shell you use.
It's a bit of a hassle to run Bash scripts this way. It would be simpler if you could just type the name of your script without the leading "bash" to make the operating system automatically start a new Bash shell to execute your script. That way, the script can be run just like any other program. To allow your script to be run without having to type the leading "bash", you must do two things:
- Change the permissions on the script to allow you to execute it. This can be done with the command "chmod u+x hello". You don't have to grant execute permission just to yourself. The command "chmod ugo+x hello" allows everyone to execute your script. See the man page for the chmod command for more information.
- Make sure that the directory containing the script is one of the directories listed in the value of your PATH environment variable.
A good way to satisfy the requirement in item #2 above is to do this:
- Create a directory named "bin" under your home directory. You can do this with the command "mkdir $HOME/bin".
- Move the script to that directory. You can do this with the command "mv hello $HOME/bin".
- List the full pathname of that directory in the value of your PATH environment variable (We cover variables in more detail in Section 4). You can do this by putting the following line into your interactive Bash startup script (which is the file .bashrc in your home directory):
Example 3 shows both the "./hello" form of the command and the "hello" form of the command. The latter only works if hello is located in a directory that is listed in the value of your PATH environment variable. In the above example, the value of PATH is changed interactively so that it contains the pathname of the bin directory under your home directory, but to make that change permanent, you should edit your .bashrc as described above and restart your shell. 2.5. Understanding the Hello World Script
Let's understand how the script shown in Example 1 works. It's just two lines long, but both lines are significant. Neither line can be left out. The first line (#!/bin/bash) tells the operating system which shell to spawn to execute this script. Unlike programs written in compiled languages, such as C, Pascal, or C++, a Bash script is interpreted, which means that some other program (the interpreter) must read the script and execute the commands in the script. Bash is the interpreter for a Bash script. A good analogy is to think of a chef cooking a meal by reading a recipe. In this case, your script is the recipe, and Bash is the chef.
The first line of your script must specify the full pathname of the Bash shell immediately after the characters "#!". If your Bash shell is installed somewhere other than /bin/bash, then you must know where it is installed and write the first line of your script accordingly. If you are using Linux, then Bash is always installed in /bin/bash. The first line in a shell script is sometimes called the shebang line. This term is derived from the use of the word "bang" to refer to an exclaimation mark and the fact that the first line of a shell script names a shell.
The second line of the script in Example 1 is an echo command. You typically use this command in an interactive shell to view the value of variables (we'll cover variables in Section 4). In a Bash script, the echo command is the general purpose mechanism for producing output. It simply outputs its arguments to the terminal on which the script is running. A single space is output betwen each argument, and a newline character is appended.
In general, Bash executes the commands in a script from top to bottom, executing each command as if it had been typed into an interactive shell. You can put any command in a Bash script that you would normally type to an interactive shell, and it will work the same way (see Section 2.6 for a short list of exceptions to this rule). But what about that shebang line (#!/bin/bash)? What happens when Bash reads and executes that line?
The answer is: nothing. The text between a "#" character and the end of the same line is a comment. A comment is completely ignored by Bash. You should use comments to make your script more readable by including information that helps the reader understand your script. We cover comments in more detail in Section 2.7.
Since the "#!/bin/bash" line is ignored by Bash, why can't you leave it out? Although it is ignored by Bash, it is not ignored by the operating system, which uses the first line of the script to determine which shell to spawn to interpret the script. Thus, the first line of the Bash script shown in Example 1 cannot be omitted, even though it is ignored by Bash.
After Bash has executed the command on the last line of the script, Bash terminates, thus terminating your script. Later, we'll see how you can control when and how your script terminates.
There is one situation where the shebang line isn't needed. If you run your script by explicitly invoking Bash, as shown in Example 2, then a shebang line isn't needed. However, you should always include a shebang line in your scripts, because you never know when you'll want to invoke the script like a regular command. Additionally, the shebang line acts to document the kind of script for human readers. 2.6. Interactive vs. Non-Interactive Shells
Before we move on to a more advanced Bash script, we should cover the few situations where the commands that you type into a Bash script work differently than the same commands typed into an interactive Bash shell. This is not a long list, but it is important to remember the following differences.
- If you have aliases defined in your personal .bashrc startup file, you cannot use those aliases in a Bash script. This is a good thing. Imagine that you could use your own personal aliases within a script. If you give that script to someone else, then it will malfunction, because the other user doesn't necessarily have the same aliases defined as you. That is why aliases are ignored by Bash when it executes a script. Aliases only work in interactive shells.
- In a Bash script, job control commands are not available. Specifically, after launching a background job by appending "&" to a command, you cannot use the bg, fg, and jobs commands to examine and manipulate the background job. You also cannot use the "kill %JOBID" form of the kill command to kill background jobs. This is not a great loss, since the job control commands were designed for interactive use, and they don't make much sense in a script.
- In a Bash script, if the exec command fails for any reason, Bash immediately terminates. This doesn't happen in an interactive shell so that you can try the exec command again.
- In a Bash script, you cannot use the history expansion character ("!") to execute previously executed commands. In fact, all command history functionality is disabled in a script (e.g., the history command is ignored).
A comment is any text following a "#" character on the same line, but the "#" character must be the first character in a word. Comments are ignored by Bash, but they help the person who reads the script to understand it. Example 4 shows a script containing some comments. This is also the first script we've seen that contains blank lines. Bash ignores blank lines, so you can use them to make your script more readable.
Example 4. Using Comments
#!/bin/bash # This script is an example of using comments. echo Hello world# This comment shares a line with a command! # The next line does _not_ contain a comment! echo Hello#world # This is also a comment. The "#" doesn't have to be # in the leftmost column. Compare the next echo # command with the previous echo command. One little # space can make a big difference! echo Hello #world
The first line in the script shown in Example 4 is the classic shebang line, described in Section 2.5. The comments should be fairly easy to see. The line that reads "echo Hello#world" contains a "#" character, but there is no comment on that line, because the "#" does not occur at the beginning of a word. The line that reads "echo Hello #world" contains a comment, because the "#" character occurs at the beginning of a word. As you can see from the output of this script, that line outputs only the text "Hello". When the above script executes, it produces this output:
Hello world Hello#world Hello
Some people think that writing comments in a script is a waste of time. Professional software engineers know this is not true. Software is hard to understand if you are not the author. Even if you are the author, it can be hard to understand long afterwards, when it isn't fresh in your mind. 20% to 50% of the lines in your scripts should be comments.