Skip to content

Instantly share code, notes, and snippets.

@neo22s
Last active June 18, 2026 16:40
Show Gist options
  • Select an option

  • Save neo22s/c7b49b4f737ec5ab7a5129ac189cc77a to your computer and use it in GitHub Desktop.

Select an option

Save neo22s/c7b49b4f737ec5ab7a5129ac189cc77a to your computer and use it in GitHub Desktop.
Adds a 1-star rating (XMP:Rating=1) to all specified JPG/JPEG/DNG/RAW files (case-insensitive), only if not already rated.
#!/bin/bash
# =====================================================
# Script: rate.sh
# Purpose: Adds a star rating (XMP:Rating + EXIF:Rating) to all
# specified JPG/JPEG/DNG/RAW files (case-insensitive),
# and optionally to their RAW pairs (CR3, ARW, NEF, etc.).
#
# Usage:
# ./rate.sh IMG_1234.JPG IMG_1235.jpg
# ./rate.sh "IMG_1234.JPG, IMG_1235.jpg"
# ./rate.sh "1Z8A4331 OR 1Z8A4373 OR 1Z8A4378"
# ./rate.sh 1Z8A4331 OR 1Z8A4373 OR 1Z8A4378
#
# Requires:
# - exiftool
# =====================================================
RATING_VALUE=1
RAW_EXTENSIONS=("CR3" "CR2" "ARW" "NEF" "RAF" "ORF" "RW2" "DNG")
if ! command -v exiftool &>/dev/null; then
echo "❌ Error: exiftool is not installed."
exit 1
fi
if [ $# -eq 0 ]; then
echo "Usage: $0 <item1> <item2> ... OR a quoted comma/OR-separated list"
exit 1
fi
# Itera argumento por argumento, filtrando "OR" con tr (compatible macOS)
INPUT_ITEMS=()
for arg in "$@"; do
upper=$(echo "$arg" | tr '[:lower:]' '[:upper:]')
[ "$upper" = "OR" ] && continue
cleaned=$(echo "$arg" | tr -d ',')
[ -z "$cleaned" ] && continue
if [[ "$cleaned" == *.* ]]; then
base="${cleaned%.*}"
else
base="$cleaned"
fi
INPUT_ITEMS+=("$base")
done
echo "🔧 Rating ${#INPUT_ITEMS[@]} images with ${RATING_VALUE} stars..."
for base in "${INPUT_ITEMS[@]}"; do
found_any=false
orig_file=$(find . -maxdepth 1 -iname "${base}.*" -type f | grep -iE '\.(jpe?g|dng)$' | head -n1)
if [[ -n "$orig_file" ]]; then
exiftool -m -overwrite_original -quiet \
-if '$Rating < 1' \
-XMP:Rating="$RATING_VALUE" \
-EXIF:Rating="$RATING_VALUE" \
"$orig_file"
echo "✔️ Rated $(basename "$orig_file")"
found_any=true
else
echo "⚠️ JPG/JPEG/DNG not found for: ${base}"
fi
for ext in "${RAW_EXTENSIONS[@]}"; do
raw_file=$(find . -maxdepth 1 -iname "${base}.${ext}" -type f | head -n1)
if [[ -n "$raw_file" ]]; then
exiftool -m -overwrite_original -quiet \
-if '$Rating < 1' \
-XMP:Rating="$RATING_VALUE" \
-EXIF:Rating="$RATING_VALUE" \
"$raw_file"
echo "✔️ Rated $(basename "$raw_file")"
found_any=true
fi
done
if [ "$found_any" = false ]; then
echo "⚠️ No files found for base name: $base"
fi
done
echo "✅ Rating complete."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment