Bash Scripting Basics: How to Write and Run Your First Linux Shell Script

Crystal sequence of instructions carrying a turquoise signal from input through a loop to a finished result. Linux & Administration
Bash scripting foundation

A Bash script is not a different kind of magic command. It is a text file that gives the shell a sequence of commands, values, and decisions to execute in a repeatable order.

Input Arguments and files
Commands Work performed in order
Decisions Exit status controls the path
Result Output and final status
Quick Answer

A Bash script is a plain-text file containing commands Bash can interpret. A shebang can select the interpreter when the file is executed directly. Variables hold values, positional parameters receive arguments, conditionals choose a path, loops repeat work, and exit statuses tell the caller whether the script succeeded.

You can run a script explicitly with bash script.sh, or make it executable and run it as ./script.sh.

What You’ll Learn

  • What Bash actually does with a script file.
  • How to create and run a first script safely.
  • How variables and script arguments differ.
  • How quoting protects values containing spaces.
  • How conditions and loops control execution.
  • How a script reports success or failure.

What Is a Bash Script?

A Bash script is a file containing shell syntax. Bash reads that file, performs expansions, runs commands, and uses their exit statuses to decide which branches or loops should continue.

The file does not become reliable merely because its commands work once in an interactive terminal. A useful script makes its inputs, interpreter, failure behavior, and observable result explicit.

This connects several earlier lessons. The shell interprets the commands . Variables provide values . Standard streams carry input and output . Exit codes drive decisions . A script puts those pieces into a reusable file.

Once a script is reliable, the next step is learning how to run it automatically. The Linux cron jobs guide explains crontab schedules, execution environments, output handling, and common failures.

TXT Plain text A script can be inspected, reviewed, and versioned like any other text file.
SH Interpreted by a shell The selected interpreter decides which syntax and features are valid.
↻ Repeatable procedure The same steps can receive different arguments and produce a documented result.

Build Your First Linux Shell Script

Create a file named hello.sh with this content:

#!/usr/bin/env bash

name=${1:-operator}
printf 'Hello, %s\n' "$name"

The first line is the shebang. When the executable file is launched directly, the operating system uses it to locate the interpreter. /usr/bin/env bash searches the current PATH for Bash. That is convenient for a learning script and many user-managed environments.

Administrative scripts may instead use #!/bin/bash when that exact path is guaranteed and choosing the system interpreter deliberately matters. The best choice depends on where the script will run.

Run it through Bash

bash hello.sh
bash hello.sh Dana

In this form, Bash is started explicitly and receives the file as input. The file itself does not need execute permission.

Run it as an executable file

chmod u+x hello.sh
./hello.sh Dana

chmod u+x gives the file’s owner execute permission. The ./ prefix tells the shell to use the file in the current directory. The shebang then selects Bash.

Useful distinction: bash hello.sh explicitly chooses Bash. ./hello.sh relies on execute permission and the interpreter declared by the shebang.

Variables, Arguments, and Quoting

A variable gives a name to a value inside the script. Bash assignments do not allow spaces around the equals sign:

service_name=web
printf 'Checking %s\n' "$service_name"

Arguments arrive as positional parameters. $1 is the first argument, $2 is the second, $# is the number of arguments, and "$@" expands to all arguments while preserving each one as a separate value.

Expression Meaning Typical use
$0 Name used to invoke the script Usage and error messages
$1 First positional argument A filename, mode, or other input
$# Number of positional arguments Validate required input
"$@" All arguments, preserved as separate words Loop safely over supplied values
$? Status of the latest foreground pipeline Capture success or failure immediately

Double quotes are essential when a value may contain spaces or wildcard characters. Compare the intent:

path="Project Files/report.txt"
printf '%s\n' "$path"

With "$path", Bash passes one argument. Without quotes, word splitting and filename expansion can change the number or meaning of arguments.

Do not test scripts only with simple names. A script that works for report.txt may fail for monthly report.txt. Quoting should reflect the data model, not the sample filename.

How Bash Scripts Make Decisions

An if statement runs commands as its condition. If that condition returns status 0, Bash executes the then branch. Otherwise, it can execute else.

file=$1

if [[ -r "$file" ]]; then
  printf '%s is readable\n' "$file"
else
  printf '%s is missing or unreadable\n' "$file" >&2
  exit 1
fi

[[ -r "$file" ]] is a Bash conditional expression that succeeds when the path exists and is readable in the current context. The error message is redirected to standard error, and exit 1 reports failure to the caller.

Choose [[ ... ]] deliberately

[[ ... ]] is Bash syntax. It offers convenient conditional behavior, but a script using it should identify Bash as its interpreter. Portable sh scripts use different constraints and commonly use test or [ ... ].

Repeat Work with a Loop

A for loop can process each argument without duplicating commands:

for path in "$@"; do
  printf 'Inspecting: %s\n' "$path"
done

Quoting "$@" preserves each original argument, including filenames containing spaces. Bash assigns one argument at a time to path and runs the loop body for it.

Construct Purpose Mental model
if Choose a branch from command status Run this when the condition succeeds
for Process a known list of values Run once for each item
while Repeat while a condition succeeds Check, run, then check again
case Match one value against patterns Choose among named modes or shapes
function Group reusable commands Give one operation a name

Mini Lab: Create a Safe Path Inspector

Safe practice

This lab works inside a temporary directory and only reads the sample paths it creates.

1
Create and enter a temporary workspace.
SA_SCRIPT_LAB=$(mktemp -d)
cd "$SA_SCRIPT_LAB" || exit 1
printf 'Workspace: %s\n' "$SA_SCRIPT_LAB"
2
Create the script.
cat > inspect-paths.sh <<'EOF'
#!/usr/bin/env bash

if (( $# == 0 )); then
  printf 'Usage: %s PATH...\n' "$0" >&2
  exit 2
fi

for path in "$@"; do
  if [[ -f "$path" ]]; then
    bytes=$(wc -c < "$path")
    printf 'File: %s (%s bytes)\n' "$path" "$bytes"
  elif [[ -d "$path" ]]; then
    printf 'Directory: %s\n' "$path"
  else
    printf 'Unavailable: %s\n' "$path" >&2
  fi
done
EOF

The quoted 'EOF' delimiter prevents the current interactive shell from expanding variables while it creates the file.

3
Check syntax without running the script.
bash -n inspect-paths.sh

No output normally means Bash found no syntax error. This does not prove that the script’s logic is correct, but it catches structural mistakes.

4
Create samples and run the script.
printf 'alpha\n' > "sample file.txt"
mkdir sample-directory
chmod u+x inspect-paths.sh

./inspect-paths.sh "sample file.txt" sample-directory missing

Observe that the filename containing a space remains one argument. The missing path produces an error message without stopping inspection of the other inputs.

5
Clean up after confirming the path.
printf 'Removing: %s\n' "$SA_SCRIPT_LAB"
cd /tmp || exit 1
rm -r -- "$SA_SCRIPT_LAB"
unset SA_SCRIPT_LAB

Common Bash Scripting Mistakes

Using the wrong interpreter A script declares Bash but is launched with sh script.sh, or it uses Bash syntax while declaring a different shell.
Leaving expansions unquoted Spaces and wildcard characters can split or expand values in unintended ways.
Forgetting input validation The script assumes $1 exists and fails later with a confusing message.
Ignoring exit status A failed command is followed by more work as though the earlier step succeeded.
Making the script executable but omitting a valid shebang Direct execution needs both permission and a usable interpreter declaration.
Adding complexity before testing the core path Build one observable step, verify it, and then add branches and loops.

Knowledge Check

1. What is a Bash script?
It is a text file containing commands and Bash syntax that the Bash interpreter can read and execute.
2. What does the shebang do?
When an executable script is launched directly, the shebang identifies the interpreter that should read it.
3. Why does bash script.sh work without execute permission?
Because Bash is the executable command. It opens the script file as input; the script itself is not being executed directly.
4. Why should "$@" usually be quoted?
Inside double quotes, it preserves every positional argument as a separate value, including arguments containing spaces.
5. What makes an if condition true in Bash?
The command or conditional expression used as the condition returns exit status 0.
6. What does bash -n script.sh verify?
It reads the script and checks its syntax without executing the commands. Logical and runtime errors can still remain.
Servers Academy — Key Takeaway

A Bash script is a repeatable conversation with the shell. Arguments provide input, variables hold values, quoting preserves their boundaries, commands perform work, conditions and loops control the path, streams carry messages, and the final exit status reports the outcome.

Start with a small script whose behavior you can observe. Validate its input, quote data values, check the commands that matter, and make success or failure clear to both people and calling programs.

Official References

Rate article
Servers Academy
Add a comment