Skip to content

Instantly share code, notes, and snippets.

@pyrodex
Last active June 2, 2025 20:27
Show Gist options
  • Save pyrodex/43526a1f916cdb1612f5e8396e09978e to your computer and use it in GitHub Desktop.
Save pyrodex/43526a1f916cdb1612f5e8396e09978e to your computer and use it in GitHub Desktop.
Script to report on Frigate usage by camera and/or date
#!/bin/bash
set -euo pipefail
usage() {
echo "Usage: $0 [-d YYYY-MM-DD [-c CAMERANAME] [-C]] [-D]"
echo "-d: Date to search in YYYY-MM-DD format"
echo "-c: (Optional) Name of the camera as Frigate knows it"
echo "-C: All cameras (use with -d)"
echo "-D: Show total disk usage per day across all cameras"
echo ""
echo "-d and -c can be used together"
echo "-d and -C can be used together"
echo "-D cannot be combined with other options"
exit 1
}
format_size() {
local size=$1
if [ "$size" -lt 1024 ]; then
echo "${size} B"
elif [ "$size" -lt $((1024 * 1024)) ]; then
printf "%.2f KB\n" "$(bc -l <<< "$size/1024")"
elif [ "$size" -lt $((1024 * 1024 * 1024)) ]; then
printf "%.2f MB\n" "$(bc -l <<< "$size/1048576")"
else
printf "%.2f GB\n" "$(bc -l <<< "$size/1073741824")"
fi
}
# Parse args
date=""
camera=""
all_cameras=false
show_days=false
while getopts "d:c:CD" opt; do
case "$opt" in
d) date="$OPTARG" ;;
c) camera="$OPTARG" ;;
C) all_cameras=true ;;
D) show_days=true ;;
*) usage ;;
esac
done
if $show_days && { [ -n "$date" ] || [ -n "$camera" ] || $all_cameras; }; then
echo "Error: -D cannot be combined with other options"
usage
fi
# === -D mode: Show usage per day ===
if $show_days; then
echo "Daily total usage across all cameras:"
declare -A day_usage
total_usage=0
for date_dir in /media/frigate/recordings/*; do
[ -d "$date_dir" ] || continue
day=$(basename "$date_dir")
size=$(du -sb "$date_dir" | awk '{print $1}')
day_usage["$day"]=$size
total_usage=$((total_usage + size))
done
for day in "${!day_usage[@]}"; do
echo "$day ${day_usage[$day]}"
done | sort | while read -r day size; do
echo "$day: $(format_size "$size")"
done
echo "Total Usage: $(format_size "$total_usage")"
exit 0
fi
# === Existing modes ===
[ -z "$date" ] && [ -z "$camera" ] && ! $all_cameras && usage
if [ -n "$date" ]; then
dir="/media/frigate/recordings/$date"
[ ! -d "$dir" ] && { echo "Error: Directory $dir does not exist."; exit 1; }
echo "Scanning $dir"
if $all_cameras; then
declare -A camera_usage
total_usage=0
while IFS= read -r -d '' cam_dir; do
cam_name=$(basename "$cam_dir")
size=$(du -sb "$cam_dir" | awk '{print $1}')
camera_usage["$cam_name"]=$(( ${camera_usage["$cam_name"]:-0} + size ))
total_usage=$((total_usage + size))
done < <(find "$dir" -mindepth 2 -maxdepth 2 -type d -print0)
echo "Camera usage for $date (sorted by size):"
for cam in "${!camera_usage[@]}"; do
echo "${camera_usage[$cam]} $cam"
done | sort -n | while read -r size cam; do
echo "$cam: $(format_size "$size")"
done
echo "Total Usage: $(format_size "$total_usage")"
else
declare -A hourly_usage
total_usage=0
for hour_dir in "$dir"/*; do
[ -d "$hour_dir" ] || continue
hour=$(basename "$hour_dir")
target_dir="$hour_dir/${camera:-}"
size=0
if [ -n "$camera" ] && [ -d "$target_dir" ]; then
size=$(du -sb "$target_dir" | awk '{print $1}')
elif [ -z "$camera" ]; then
size=$(du -sb "$hour_dir" | awk '{print $1}')
fi
hourly_usage["$hour"]=$size
total_usage=$((total_usage + size))
done
echo "Hourly usage for $date${camera:+ (Camera: $camera)}:"
for hour in $(seq -w 0 23); do
echo "Hour $hour: $(format_size ${hourly_usage[$hour]:-0})"
done
echo "Total Usage: $(format_size "$total_usage")"
fi
else
echo "Scanning all dates for Camera: $camera"
declare -A daily_usage
total_usage=0
for date_dir in /media/frigate/recordings/*; do
[ -d "$date_dir" ] || continue
date=$(basename "$date_dir")
day_total=0
while IFS= read -r -d '' hour_dir; do
cam_dir="$hour_dir/$camera"
[ -d "$cam_dir" ] || continue
size=$(du -sb "$cam_dir" | awk '{print $1}')
day_total=$((day_total + size))
done < <(find "$date_dir" -mindepth 1 -maxdepth 1 -type d -print0)
daily_usage["$date"]=$day_total
total_usage=$((total_usage + day_total))
done
echo "Daily usage for Camera: $camera"
for day in $(printf "%s\n" "${!daily_usage[@]}" | sort); do
echo "$day: $(format_size "${daily_usage[$day]}")"
done
echo "Total Usage for Camera $camera: $(format_size "$total_usage")"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment