Last active
June 2, 2025 20:27
-
-
Save pyrodex/43526a1f916cdb1612f5e8396e09978e to your computer and use it in GitHub Desktop.
Script to report on Frigate usage by camera and/or date
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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