Bash Scripting for Beginners: Automate the Commands You Keep Typing
A bash script is a text file of terminal commands you can run in one go. How to write and run your first script, variables, arguments, if-statements and loops, the safety line every script should start with, and a real deploy script you can adapt.
If you find yourself typing the same five terminal commands every day, you can put them in a file and run them with one command. That file is a shell script, and the most common kind is a bash script.
(New to the terminal? Read the terminal for complete beginners first.)
Your first script
Create a file called hello.sh:
#!/usr/bin/env bash
echo "Hello! Today is $(date +%A)."
The first line — the shebang — tells the system to run this file with bash. Then make it executable and run it:
chmod +x hello.sh
./hello.sh
The ./ means "the file in this folder." (Linux file permissions explains chmod +x.)
Start every script with this line
#!/usr/bin/env bash
set -euo pipefail
By default bash keeps going after a command fails — which can be disastrous (imagine cd failing, then rm -rf * running in the wrong folder). This line makes the script safer:
-e— stop if any command fails.-u— stop if you use a variable that was never set (catches typos).-o pipefail— a failure in the middle of a|pipeline counts as a failure.
Variables
name="my-app"
echo "Deploying $name"
echo "Backup file: ${name}-backup.sql"
Rules that trip everyone up:
- No spaces around
=.name = "x"is an error. - Always quote variables:
"$name". Without quotes, a value with spaces breaks into multiple words. - Capture a command's output with
$(...):today=$(date +%F).
Environment variables work the same way: echo "$HOME". (Environment variables explained)
Arguments
Values passed to the script are $1, $2, …; $@ is all of them.
#!/usr/bin/env bash
set -euo pipefail
env="${1:-staging}" # first argument, default "staging"
echo "Deploying to $env"
./deploy.sh production
If-statements
if [[ -f .env ]]; then
echo ".env exists"
else
echo "Missing .env" >&2
exit 1
fi
Handy tests:
| Test | True when |
|---|---|
-f file |
File exists |
-d dir |
Folder exists |
-z "$var" |
Variable is empty |
"$a" == "$b" |
Strings are equal |
$n -gt 5 |
Number greater than 5 |
exit 1 stops the script with a failure code; >&2 sends the message to the error output.
You can also branch on whether a command succeeded:
if ! command -v node >/dev/null; then
echo "Node.js is not installed" >&2
exit 1
fi
Loops
for file in backups/*.sql; do
echo "Found $file"
done
Functions
log() { echo "[$(date +%T)] $*"; }
log "Starting deploy"
A real example: a simple deploy script
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")" # run from the script's own folder
log() { echo "[$(date +%T)] $*"; }
log "Pulling latest code"
git pull --ff-only
log "Installing dependencies"
npm ci
log "Running migrations"
npm run migrate
log "Building"
npm run build
log "Restarting"
pm2 reload my-app
log "Done"
Because of set -e, if the build fails, the restart never happens — your old version keeps running.
Debugging a script
Run it with bash -x script.sh to print each command before it runs. And install ShellCheck (brew install shellcheck, or the VS Code extension): it catches the quoting mistakes and gotchas that bite everyone.
Bash, sh, zsh, PowerShell?
- bash — the default on most Linux servers. Scripts you'll deploy should target it.
- zsh — the default interactive shell on macOS. Runs most bash scripts fine, but use the bash shebang anyway.
- sh — a more minimal shell; some features above (like
[[ ]]) aren't available. - PowerShell — Windows' shell, different syntax. Use WSL to run bash on Windows. (What is WSL?)
The summary
- A script is a file of commands with
#!/usr/bin/env bashon top. - Always add
set -euo pipefail. - No spaces around
=, and quote your variables. $1for arguments,[[ ]]for tests,forfor loops.bash -xand ShellCheck find most problems.
EasySpawn gives you a persistent Linux server with a real terminal, where your scripts — and Claude Code — can run on a schedule or on demand. See how it works or join the waitlist.
Related: The Terminal for Complete Beginners · Cron Expressions Explained · What Is Linux? · The PATH Variable and "Command Not Found"
Keep reading
What Is WSL? Running Linux on Windows, Explained
WSL lets you run a real Linux system inside Windows without dual-booting or a separate virtual machine to manage. What it is, why web developers use it, how to install it, where your files live, and the performance and networking gotchas.
What Is an IDE? Code Editors vs IDEs Explained
An IDE (integrated development environment) puts everything you need to write software in one app: editor, file browser, terminal, debugger, git and more. How it differs from a plain code editor, the popular options, cloud IDEs, and where AI fits in.