← Back to Bash Course | Chapter 14: Best Practices & Real-World Scripting | Lesson 4 of 7

Idempotent Scripts (Safe to Re-Run)

An idempotent script gives the same end result no matter how many times you run it, instead of causing problems the second time.

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

bash
#!/bin/bash
mkdir -p app_data
mkdir -p app_data
echo "directory ready, and running this twice caused no error"
rmdir app_data

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

bash
#!/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

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

bash
#!/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

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

bash
#!/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"
Common Mistakes
  1. Using mkdir without -p in a setup script, which errors out on every run after the first because the directory already exists.
  2. Appending to a file every run without checking if the content is already there, resulting in duplicated entries over time.
  3. Assuming a script that "worked once" is safe to re-run automatically without considering what happens if some steps already completed.
Chapter Summary
  • 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 using ln -sf instead of plain ln -s are 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.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.