#!/bin/bash # ----------------------------------------------------------------------------------------------- # --------------------------------- Media Cleaner Script --------------------------------------- # ----------------------------------------------------------------------------------------------- # Removes unwanted files from media share folders using configurable file patterns. # Supports two profiles: anime and media — each with their own folder list and file patterns. # Profiles and patterns are configured in Master.conf. # Supports --dry-run to preview what would be deleted without making changes. # # Usage: # media_cleaner.sh anime — clean anime shares # media_cleaner.sh media — clean media shares # media_cleaner.sh anime --dry-run — preview anime clean # ----------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" # ----------------------------------------------------------------------------------------------- # Separate profile argument from flags # ----------------------------------------------------------------------------------------------- PROFILE="" RAW_ARGS=() for ARG in "$@"; do case "$ARG" in --*|*=*) RAW_ARGS+=("$ARG") ;; anime|media) PROFILE="$ARG" ;; *) RAW_ARGS+=("$ARG") ;; esac done parse_args "${RAW_ARGS[@]}" # ----------------------------------------------------------------------------------------------- # ━━━ $ICON_GEAR Setup ━━━ # ----------------------------------------------------------------------------------------------- echo "" echo "━━━ $ICON_GEAR Setup ━━━" if [[ "$EUID" -ne 0 ]]; then error "Must be run as root" exit 1 fi success "Running as root" acquire_lock "wait" if ! command -v find >/dev/null 2>&1; then error "find command not found — check findutils installation" exit 1 fi if [[ -z "$PROFILE" ]]; then error "No profile specified. Usage: media_cleaner.sh [--dry-run]" exit 1 fi # Resolve profile folders and patterns case "$PROFILE" in anime) CLEAN_FOLDERS=("${ANIME_CLEAN_FOLDERS[@]}") FILE_PATTERNS=("${ANIME_FILE_PATTERNS[@]}") ;; media) CLEAN_FOLDERS=("${MEDIA_CLEAN_FOLDERS[@]}") FILE_PATTERNS=("${MEDIA_FILE_PATTERNS[@]}") ;; *) error "Unknown profile: $PROFILE — must be anime or media" exit 1 ;; esac info "$ICON_GEAR Profile: $PROFILE" info "$ICON_CLEAN Folders: ${#CLEAN_FOLDERS[@]}" info "$ICON_TRASH Patterns: ${#FILE_PATTERNS[@]}" # ----------------------------------------------------------------------------------------------- # ━━━ $ICON_SUMMARY Status ━━━ # ----------------------------------------------------------------------------------------------- if [[ "$SHOW_STATUS" == true ]]; then echo "" echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━" echo "$ICON_GEAR Profile: $PROFILE" echo "$ICON_CLEAN Folders: ${CLEAN_FOLDERS[*]}" echo "$ICON_TRASH Patterns: ${FILE_PATTERNS[*]}" echo "$ICON_GEAR Dry Run: $DRY_RUN" echo "━━━━━━━━━━━━━━━━━━━━━━━" exit 0 fi [[ "$DRY_RUN" == true ]] && warn "DRY RUN — no files will be deleted" # ----------------------------------------------------------------------------------------------- # ━━━ $ICON_CLEAN Media Cleaner ━━━ # ----------------------------------------------------------------------------------------------- echo "" echo "━━━ $ICON_CLEAN Media Cleaner — $PROFILE ━━━" echo "" START=$(date +%s) TOTAL_REMOVED=0 FAILED=() SKIPPED=() for FOLDER in "${CLEAN_FOLDERS[@]}"; do FOLDER_NAME=$(basename "$FOLDER") echo "━━━ $ICON_CLEAN $FOLDER_NAME ━━━" if [[ ! -d "$FOLDER" ]]; then warn "$FOLDER_NAME not found — skipping" SKIPPED+=("$FOLDER_NAME") echo "" continue fi # Build find command dynamically from FILE_PATTERNS array CMD=(find "$FOLDER" -type f \() for ((i = 0; i < ${#FILE_PATTERNS[@]}; i++)); do CMD+=(-iname "${FILE_PATTERNS[i]}") if [[ $i -lt $(( ${#FILE_PATTERNS[@]} - 1 )) ]]; then CMD+=(-o) fi done CMD+=(\)) # Count matching files before acting FILE_COUNT=$("${CMD[@]}" 2>/dev/null | wc -l) if [[ "$FILE_COUNT" -eq 0 ]]; then success "$FOLDER_NAME — no matching files found" echo "" continue fi info "$ICON_TRASH $FILE_COUNT file(s) found in $FOLDER_NAME" if [[ "$DRY_RUN" == true ]]; then warn "DRY RUN — files that would be deleted:" "${CMD[@]}" 2>/dev/null | while IFS= read -r f; do echo " $ICON_TRASH $f" done else CLEAN_CMD=("${CMD[@]}" -exec rm -f {} +) if "${CLEAN_CMD[@]}" 2>/dev/null; then success "$FOLDER_NAME — $FILE_COUNT file(s) removed" TOTAL_REMOVED=$((TOTAL_REMOVED + FILE_COUNT)) else error "$FOLDER_NAME — cleanup failed" FAILED+=("$FOLDER_NAME") fi fi echo "" done END=$(date +%s) # ----------------------------------------------------------------------------------------------- # ━━━ $ICON_SUMMARY Summary ━━━ # ----------------------------------------------------------------------------------------------- echo "━━━━━ $ICON_SUMMARY MEDIA CLEANER SUMMARY ━━━━━" echo "$ICON_GEAR Profile: $PROFILE" echo "$ICON_TIME Duration: $(format_duration $((END - START)))" [[ ${#SKIPPED[@]} -gt 0 ]] && echo "$ICON_WARN Skipped: ${SKIPPED[*]}" [[ ${#FAILED[@]} -gt 0 ]] && echo "$ICON_ERROR Failed: ${FAILED[*]}" if [[ "$DRY_RUN" == true ]]; then echo "$ICON_WARN Status: DRY RUN — no files deleted" elif [[ ${#FAILED[@]} -gt 0 ]]; then echo "$ICON_ERROR Status: $ICON_ERROR SOME FOLDERS FAILED" notify "Media cleaner ($PROFILE) failed on $(hostname) — ${FAILED[*]}" "Media Cleaner" "warning" else echo "$ICON_TRASH Removed: $TOTAL_REMOVED file(s)" echo "$ICON_DONE Status: $ICON_SUCCESS DONE" notify "Media cleaner ($PROFILE) complete on $(hostname) — $TOTAL_REMOVED file(s) removed" "Media Cleaner" "normal" fi echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" [[ ${#FAILED[@]} -gt 0 ]] && exit 1 exit 0