Intermediate Bash Scripting Mastery
Script Foundations
From Commands to Scripts
You've likely spent time typing commands into a terminal one by one. This is great for direct interaction, but what about tasks you perform repeatedly? Chaining commands together in a text file creates a script, a reusable program that automates your work. Think of it as a recipe the computer follows, executing each command in order.
A shell script is simply a text file containing a sequence of commands for a command-line interpreter.
Creating a script is as simple as opening a text editor and writing the commands you would normally type. However, to make it a robust and reliable tool, a few conventions are essential. Let's build a proper script from the ground up.
The Anatomy of a Script
Every well-formed script begins with a special line called a shebang or hashbang. It tells the operating system which interpreter should be used to execute the commands in the file. For Bash scripts, this is typically #!/bin/bash.
A more portable and recommended approach is to use #!/usr/bin/env bash. This uses the env command to find the Bash interpreter in the user's PATH. This way, the script will work even if Bash is installed in a non-standard location, like /usr/local/bin/bash instead of /bin/bash.
#!/usr/bin/env bash
# A simple script to greet the user and show the current date.
# Comments like this one are ignored by the interpreter.
# 1. Define a variable
USERNAME="Alex"
# 2. Use the variable in a command
echo "Hello, ${USERNAME}!"
# 3. Run another command
echo "The current date is:"
date
Following the shebang, it's crucial to add comments. A comment is any line that begins with a # symbol. The interpreter ignores these lines, but they are invaluable for humans. Good comments explain the why behind your code, not just the what. They document the script's purpose, describe complex logic, or leave notes for future you.
Making Scripts Executable
Once you've saved your script (let's call it hello.sh), you can't run it directly just yet. By default, new text files don't have permission to be executed. You need to grant this permission using the chmod command, which stands for "change mode."
chmod +x hello.sh
The +x part adds the executable permission for the user, group, and others. Now the file is marked as a program that can be run.
To execute it, you'll typically type:
./hello.sh
The ./ prefix is important. It explicitly tells the shell to look for the hello.sh file in the current directory (.). This is a security feature that prevents you from accidentally running a malicious script with the same name as a standard command (like ls) that might be in your current folder.
Executing vs. Sourcing
There are two primary ways to run a script, and the difference is crucial. When you execute a script with ./hello.sh, the system creates a new, separate shell process (a subshell) to run the commands. Any changes the script makes to its environment, such as defining variables or changing directories with cd, happen inside that subshell. When the script finishes, the subshell disappears, and all those changes are lost. Your original shell session remains completely unaffected.
Let's look at a script named vars.sh:
#!/usr/bin/env bash
MY_VARIABLE="I exist only within the script."
echo "Inside script: ${MY_VARIABLE}"
If you make it executable and run it, you'll see the output. But if you then try to access the variable in your terminal, it won't be there.
The other method is sourcing a script. This runs the commands directly within the current shell session. No subshell is created. Any variables defined or directories changed will persist after the script finishes.
You source a script using either the source command or its shorthand, the dot . character.
# Using the source command
source vars.sh
# Using the dot shorthand (followed by a space)
. vars.sh
If you source the vars.sh script and then run echo "${MY_VARIABLE}", the variable's value will be printed, because it now exists in your active terminal session. Sourcing is often used for configuration files that set up environment variables or functions you want to use interactively, like .bashrc or .bash_profile.
What is the primary purpose of the #!/bin/bash line at the beginning of a shell script?
You have a script named setup.sh that contains export MY_VAR="hello". You want the MY_VAR variable to be available in your current terminal session after the script has finished. Which command should you use?