Idempotent Scripts (Safe to Re-Run)
In this page:
Idempotent Directory Creation
mkdir -p succeeds silently whether the directory already exists or not, unlike plain mkdir, which errors on the second run. Running this twice produces the same outcome both times.
Example: Idempotent Directory Creation
#!/bin/bash
mkdir -p app_data
mkdir -p app_data
echo "directory ready, and running this twice caused no error"
rmdir app_data
Login to try C/C++/Java/PHP code in the editor
Avoiding Duplicate Appends
Checking whether a line already exists in a file before appending it prevents a setup script from accumulating duplicate entries every time it is re-run.
Note: grep -qxF matches the WHOLE line exactly and treats the pattern as a literal string, avoiding both partial matches and regex surprises.
Example: Avoiding Duplicate Appends
#!/bin/bash
config_line="export APP_ENV=production"
touch profile.sh
add_once() {
grep -qxF "$1" "$2" || echo "$1" >> "$2"
}
add_once "$config_line" profile.sh
add_once "$config_line" profile.sh
echo "line count after running twice: $(wc -l < profile.sh)"
rm -f profile.sh
Login to try C/C++/Java/PHP code in the editor
Idempotent Symlink Creation
ln -sf overwrites an existing symlink instead of failing when it already points somewhere, whereas plain ln -s errors out if the link already exists, making -f the safer choice for scripts that may run more than once.
Example: Idempotent Symlink Creation
#!/bin/bash
touch real_file_v1.txt real_file_v2.txt
ln -sf real_file_v1.txt current.txt
ln -sf real_file_v2.txt current.txt
echo "symlink now points to: $(readlink current.txt)"
rm -f real_file_v1.txt real_file_v2.txt current.txt
Login to try C/C++/Java/PHP code in the editor
Guarding One-Time Actions
For actions that truly should only happen once (like an initial database seed), checking for a marker file or condition before running them lets a script be re-run safely without repeating that action.
Example: Guarding One-Time Actions
#!/bin/bash
marker=".initialized"
if [[ -f $marker ]]; then
echo "already initialized, skipping setup"
else
echo "running one-time setup"
touch "$marker"
fi
rm -f "$marker"
Login to try C/C++/Java/PHP code in the editor
- Using
mkdirwithout-pin a setup script, which errors out on every run after the first because the directory already exists. - Appending to a file every run without checking if the content is already there, resulting in duplicated entries over time.
- Assuming a script that "worked once" is safe to re-run automatically without considering what happens if some steps already completed.
- An idempotent operation produces the same result whether run once or many times, which matters for setup scripts, deployments, and cron jobs.
mkdir -p, checking before appending, and usingln -sfinstead of plainln -sare common idempotency techniques.- Guard destructive or one-time actions with an existence check before performing them.
- Designing for idempotency up front is much easier than retrofitting it after a script has caused duplicate side effects.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first:
- Quoting Pitfalls and Why to Always Quote Variables
- set -euo pipefail as a Script Header
- Structuring a Script (Functions, main() Pattern, Exit at the End)
- Idempotent Scripts (Safe to Re-Run)
- Logging in Scripts (Timestamped log Function)
- Writing Portable Scripts (Bash-isms vs POSIX sh)
- Capstone: A Real-World Backup/Cleanup Script