find deleted files

Sometimes you want to compare an archive backup drive and a target folder and see what items got  deleted in that folder. Useful if you have a flaky backup system like dropbox.

#!/usr/bin/env bash
# find_deleted.sh — list non-image files that exist in SOURCE but not in TARGET
# usage: ./find_deleted.sh [--rsync-check] SOURCE_DIR TARGET_DIR
set -euo pipefail
usage() {
  echo "Usage: $0 [--rsync-check] SOURCE_DIR TARGET_DIR" >&2
  exit 1
}
RSYNC_CHECK=0
if [ "${1:-}" = "--rsync-check" ]; then
  RSYNC_CHECK=1
  shift
fi
[ $# -eq 2 ] || usage
SRC="${1%/}"
DST="${2%/}"
[ -d "$SRC" ] || { echo "Source not found: $SRC" >&2; exit 2; }
[ -d "$DST" ] || { echo "Target not found: $DST" >&2; exit 3; }
# Returns 0 if the path looks like an image, 1 otherwise.
is_image_path() {
  # lower-case path (Bash-only ${var,,})
  local p="${1,,}"
  case "$p" in
    *.jpg|*.jpeg|*.png|*.gif|*.bmp|*.tif|*.tiff|*.webp|*.heic|*.heif|*.svg|\
    *.cr2|*.nef|*.arw|*.dng|*.rw2|*.orf|*.raf)
      return 0 ;;
    *)  return 1 ;;
  esac
}
missing_count=0
image_skipped=0
scanned=0
echo "Scanning (non-images only). Source: $SRC  Target: $DST" >&2
# Use a pipeline instead of process substitution for /bin/sh safety (still Bash script).
find "$SRC" -type f -print0 | while IFS= read -r -d '' f; do
  scanned=$((scanned + 1))
  rel="${f#"$SRC"/}"
  if is_image_path "$rel"; then
    image_skipped=$((image_skipped + 1))
    continue
  fi
  tgt="$DST/$rel"
  if [ ! -e "$tgt" ]; then
    echo "$rel"
    missing_count=$((missing_count + 1))
  fi
  # Lightweight progress feedback every 500 files
  if [ $((scanned % 500)) -eq 0 ]; then
    echo "…scanned $scanned (missing so far: $missing_count, images skipped: $image_skipped)" >&2
  fi
done
echo "Done. Scanned: $scanned; Missing (non-images): $missing_count; Images skipped: $image_skipped" >&2
# Optional cross-check using rsync (dry-run, excludes images).
if [ "$RSYNC_CHECK" -eq 1 ]; then
  echo >&2
  echo "rsync dry-run cross-check (non-images). Differences rsync would copy from SRC->DST:" >&2
  rsync -ani \
    --exclude='*.jpg'  --exclude='*.jpeg' --exclude='*.png'  --exclude='*.gif'  \
    --exclude='*.bmp'  --exclude='*.tif'  --exclude='*.tiff' --exclude='*.webp' \
    --exclude='*.heic' --exclude='*.heif' --exclude='*.svg'  --exclude='*.cr2'  \
    --exclude='*.nef'  --exclude='*.arw'  --exclude='*.dng'  --exclude='*.rw2'  \
    --exclude='*.orf'  --exclude='*.raf' \
    --delete --ignore-existing \
    "$SRC/" "$DST/" | sed 's/^/> /' >&2
  echo "Note: rsync output is informational only (dry run). No changes made." >&2
fi

Popular posts from this blog

Automatically Fix Song Metadata and Filenames on Linux with Beets

throttle traffic on apache

script to show all files with disk usage sizes