Skip to content

Instantly share code, notes, and snippets.

@mcisback
Last active December 12, 2025 21:30
Show Gist options
  • Select an option

  • Save mcisback/374c0c34e1564910954315245d50c642 to your computer and use it in GitHub Desktop.

Select an option

Save mcisback/374c0c34e1564910954315245d50c642 to your computer and use it in GitHub Desktop.
rm protection and guards in bash
# Put this in your .bashrc
# Load it with source ~/.bashrc
rm() {
local YES="false"
local args=()
local protected_dirs=(
"/"
"/Volumes"
"/Applications"
"/bin"
"/cores"
"/dev"
"/etc"
"/home"
"/Library"
"/opt"
"/private"
"/sbin"
"/System"
"/tmp"
"/Users"
"/usr"
"/var"
"$HOME"
"$HOME/Desktop"
"$HOME/Documents"
"$HOME/Documents/TODO.txt_Private"
"$HOME/Downloads"
"$HOME/Pictures"
"$HOME/Applications"
"$HOME/Dev"
"$HOME/Dropbox"
"$HOME/.go"
"$HOME/go"
"$HOME/Library"
"$HOME/Movies"
"$HOME/Music"
"$HOME/Parallels"
"$HOME/Programs"
"$HOME/Public"
"$HOME/Test"
)
for arg in "$@"; do
if [[ "$arg" == "--yes" ]]; then
YES="true"
else
args+=("$arg")
fi
done
block() {
echo "🚫 rm blocked"
echo " Protected target: $1"
echo " Use --yes if you are absolutely sure."
# IMPORTANT: This doesn't stop the script and it must be stopped
return 1
}
# True if target is exactly: DIR/* DIR/. DIR/..
is_wipe_of_dir() {
local target="$1"
local dir="$2"
[[ "$target" == "$dir"/* ]] && [[ "${target#$dir/}" == "*" ]] && return 0
[[ "$target" == "$dir"/ ]] && return 0
[[ "$target" == "$dir/." || "$target" == "$dir/.." ]] && return 0
return 1
}
# Normalize path; keep glob literal if it contains '*'
normalize() {
local p="$1"
if [[ "$p" == *"*"* ]]; then
# Expand ~ but keep glob
if [[ "$p" == "~/"* ]]; then
echo "$HOME/${p#~/}"
else
echo "$p"
fi
else
realpath -m -- "$p" 2>/dev/null || echo "$p"
fi
}
STOP="false"
for target in "${args[@]}"; do
local resolved
resolved="$(normalize "$target")"
for dir in "${protected_dirs[@]}"; do
local dnorm
dnorm="$(normalize "$dir")"
# 1) rm ... DIR -> block
if [[ "$resolved" == "$dnorm" ]]; then
if [[ "$YES" == "true" ]]; then
STOP="true"
break
fi
block "$resolved"
# STOP THE SCRIPT
# Cannot use exit as it closes the shell
return 1
fi
if is_wipe_of_dir "$resolved" "$dnorm"; then
if [[ "$YES" == "true" ]]; then
STOP="true"
break
fi
block "$resolved"
return 1
fi
done
if [[ "$STOP" == "true" ]]; then
break
fi
done
echo "✅ Removing ${args[@]}"
command /bin/rm "${args[@]}"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment