Skip to content

Instantly share code, notes, and snippets.

@ralph
Created February 17, 2026 15:26
Show Gist options
  • Select an option

  • Save ralph/6d1e535267a99cf1fe52b504e1f25853 to your computer and use it in GitHub Desktop.

Select an option

Save ralph/6d1e535267a99cf1fe52b504e1f25853 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Example file structure:
# .
# ├── jpg
# │   ├── 123.jpg
# │   ├── 789.jpg
# │   └── 890.jpg
# └── raw
# ├── 123.raw
# ├── 456.raw
# └── 789.raw
#
# ❯ ./compare_folders.sh raw jpg
# Only in raw:
# raw/456.raw
#
# Only in jpg:
# jpg/890.jpg
#
# ========================================
# WARNING: Deletion is PERMANENT and
# UNRECOVERABLE! Files will NOT go to Trash.
# ========================================
#
# Would you like to delete the unmatched files?
# 1) Delete files in raw that are missing in jpg
# 2) Delete files in jpg that are missing in raw
# 3) Do nothing and exit
#
# Choose [1/2/3]:
#
if [ $# -lt 2 ]; then
echo "Usage: $0 <folder1> <folder2>"
exit 1
fi
dir1="$1"
dir2="$2"
# Extract basenames without extensions
names1=$(ls "$dir1" | sed 's/\.[^.]*$//' | sort)
names2=$(ls "$dir2" | sed 's/\.[^.]*$//' | sort)
only_in_1=$(comm -23 <(echo "$names1") <(echo "$names2"))
only_in_2=$(comm -13 <(echo "$names1") <(echo "$names2"))
if [ -n "$only_in_1" ]; then
echo "Only in $dir1:"
for name in $only_in_1; do
ls "$dir1"/"$name".* 2>/dev/null
done
echo ""
fi
if [ -n "$only_in_2" ]; then
echo "Only in $dir2:"
for name in $only_in_2; do
ls "$dir2"/"$name".* 2>/dev/null
done
echo ""
fi
if [ -z "$only_in_1" ] && [ -z "$only_in_2" ]; then
echo "All file basenames match between the two folders."
exit 0
fi
# Offer to delete
echo "========================================"
echo "WARNING: Deletion is PERMANENT and"
echo "UNRECOVERABLE! Files will NOT go to Trash."
echo "========================================"
echo ""
echo "Would you like to delete the unmatched files?"
echo " 1) Delete files in $dir1 that are missing in $dir2"
echo " 2) Delete files in $dir2 that are missing in $dir1"
echo " 3) Do nothing and exit"
echo ""
read -rp "Choose [1/2/3]: " choice
case "$choice" in
1)
if [ -z "$only_in_1" ]; then
echo "No unmatched files in $dir1. Nothing to delete."
exit 0
fi
echo ""
echo "The following files will be PERMANENTLY deleted:"
for name in $only_in_1; do
ls "$dir1"/"$name".* 2>/dev/null
done
echo ""
read -rp "Are you sure? Type YES to confirm: " confirm
if [ "$confirm" = "YES" ]; then
for name in $only_in_1; do
rm -v "$dir1"/"$name".* 2>/dev/null
done
echo "Done."
else
echo "Aborted."
fi
;;
2)
if [ -z "$only_in_2" ]; then
echo "No unmatched files in $dir2. Nothing to delete."
exit 0
fi
echo ""
echo "The following files will be PERMANENTLY deleted:"
for name in $only_in_2; do
ls "$dir2"/"$name".* 2>/dev/null
done
echo ""
read -rp "Are you sure? Type YES to confirm: " confirm
if [ "$confirm" = "YES" ]; then
for name in $only_in_2; do
rm -v "$dir2"/"$name".* 2>/dev/null
done
echo "Done."
else
echo "Aborted."
fi
;;
*)
echo "No files deleted."
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment