100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Bash

Writing Your First Bash Script

Get hands-on with the anatomy of a Bash script — shebang, permissions, execution, comments, and structuring commands into a reusable, repeatable tool.

Bash Scripting FundamentalsBeginner8 min readJul 9, 2026
Analogies

Writing Your First Bash Script

A Bash script is simply a text file containing a sequence of shell commands that Bash executes in order, exactly as if you had typed them interactively. Scripting turns repetitive manual work — backups, deployments, log rotation, environment setup — into a single reliable, version-controllable command. The barrier to writing your first script is low: you need a text file, a shebang line telling the kernel which interpreter to use, executable permission, and a location the shell can find. From there, everything you already know about running commands at the prompt applies inside the script.

🏏

Cricket analogy: A training script is simply a written sequence of drills a coach runs through in order, exactly as if calling them out live; turning repetitive nets sessions into one documented routine needs a written plan, a header naming the coach in charge, sign-off to run it, and a spot in the team's training folder.

The shebang and how scripts are executed

The first line of a script, #!/bin/bash (or the more portable #!/usr/bin/env bash), is called the shebang. The kernel reads these first two bytes (#!) and uses the rest of the line to determine which interpreter should run the file — this is how ./script.sh knows to invoke Bash rather than trying to execute the text as a binary. #!/usr/bin/env bash is preferred in portable scripts because it locates bash via the user's PATH rather than assuming it lives at /bin/bash, which matters on systems (like some macOS setups or containers) where Bash is installed elsewhere. If you omit the shebang and instead run the script as bash script.sh, the shebang line is ignored and treated as a comment.

🏏

Cricket analogy: The team sheet's header line names the format being played (Test vs T20), and officials read just that header to know which rulebook applies before the toss; naming the format generically as 'limited overs' (like #!/usr/bin/env bash) is more portable across grounds than hardcoding one ground's rules, and if you skip the header, the format assumption is ignored entirely.

bash
#!/usr/bin/env bash
#
# backup-home.sh — archive the current user's home directory
# Usage: ./backup-home.sh [destination-dir]

set -euo pipefail   # exit on error, unset variable, or failed pipeline stage

dest="${1:-/var/backups}"
timestamp="$(date +%Y%m%d-%H%M%S)"
archive="${dest}/home-backup-${timestamp}.tar.gz"

mkdir -p "$dest"
tar -czf "$archive" -C "$HOME" .

echo "Backup written to $archive"
ls -lh "$archive"

Making a script executable and running it

Newly created scripts are not executable by default; chmod +x script.sh adds the executable bit for the owner (and typically group/other depending on umask). Once executable, ./script.sh runs it from the current directory — the leading ./ is required unless the script's directory is in your PATH, because Bash does not search the current directory for commands by default (a deliberate security measure). Alternatively, bash script.sh or sh script.sh runs it by explicitly invoking an interpreter, bypassing both the shebang and the need for the executable bit, though sh may interpret Bash-specific syntax differently.

🏏

Cricket analogy: A newly registered player isn't automatically cleared to play (chmod +x) — the board must certify them first; even then, you must name them explicitly on the team sheet (./script.sh) rather than assume selectors will notice by default, since committees don't scan the crowd for unlisted talent; alternatively, a wildcard entry (bash script.sh) bypasses certification but may be interpreted differently under a different format's rules.

bash
chmod +x backup-home.sh
./backup-home.sh /mnt/backups

# Or run without the executable bit at all
bash backup-home.sh /mnt/backups

# Install it on PATH so it can be called by name anywhere
sudo cp backup-home.sh /usr/local/bin/backup-home
sudo chmod +x /usr/local/bin/backup-home
backup-home

set -euo pipefail is often called Bash's 'strict mode.' -e exits immediately if any command returns non-zero, -u treats referencing an unset variable as an error rather than silently substituting an empty string, and -o pipefail makes a pipeline fail if any stage fails, not just the last one. Together they catch classes of bugs — typoed variable names, silently swallowed errors — that make ad-hoc scripts unreliable in production.

set -e does not catch every failure: it is bypassed inside if conditions, inside &&/|| chains, and for commands whose exit status is checked directly. A common surprise is that a failing command inside a pipeline still lets the script continue unless pipefail is also set, since -e alone only inspects the pipeline's overall (last-command) exit status.

Structure, comments, and style

Good scripts start with a comment block describing purpose and usage, use set -euo pipefail near the top, quote variables, and prefer functions for anything reused more than once. Comments begin with # and run to the end of the line; there is no native multi-line comment syntax, though a : <<'END' here-document is sometimes used as a workaround. Keeping scripts under version control (even a small personal Git repo of ~/.local/bin scripts) is standard practice once you have more than a handful.

🏏

Cricket analogy: A well-prepared team keeps a written game plan header explaining strategy, sets a 'stop immediately on any collapse' rule (set -euo pipefail) rather than playing on through disaster, names players precisely to avoid mix-ups, and reuses a standard fielding drill (a function) rather than re-explaining it each time; notes use a quick marginal comment (#), and the game plan is archived season over season like a version-controlled playbook.

  • A script's first line, the shebang (#!/usr/bin/env bash), tells the kernel which interpreter to execute it with.
  • chmod +x grants execute permission; ./script.sh runs it from the current directory since PATH excludes . by default.
  • set -euo pipefail is standard 'strict mode' that fails fast on errors, unset variables, and failed pipeline stages.
  • Running a script as bash script.sh bypasses the shebang and the need for the executable bit.
  • Comments start with #; there is no built-in multi-line comment, though a here-doc trick can approximate one.
  • Scripts placed on your PATH (e.g. /usr/local/bin) can be invoked by name from anywhere on the system.

Practice what you learned

Was this page helpful?

Topics covered

#Bash#LinuxShellScriptingStudyNotes#DevOps#WritingYourFirstBashScript#Writing#Script#Shebang#Scripts#StudyNotes#SkillVeris