611 lines
26 KiB
Bash
Executable File
611 lines
26 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Script to organize MP4 files by studio name with video metadata
|
|
# Format: Studio - Performer(s) - Title [DD-MM-YYYY] [H:MM] [Quality] [H/V].mp4
|
|
|
|
# Enable strict error handling
|
|
set -o pipefail # Catch failures in piped commands
|
|
|
|
# Use environment variable if set (for Docker), otherwise use default path
|
|
ROOT_DIR="${SOURCE_LIBRARY:-/media/bunker-admin/Internal/plex/xxx/media/local/studios}"
|
|
GIFS_DIR="${GIFS_PATH:-/media/bunker-admin/Internal/plex/xxx/media/local/gifs}"
|
|
INBOX_DIR="${INBOX_PATH:-/media/bunker-admin/Internal/plex/xxx/media/local/inbox}"
|
|
COMPILATIONS_DIR="${COMPILATIONS_PATH:-/media/bunker-admin/Internal/plex/xxx/media/public/compilations}"
|
|
|
|
cd "$ROOT_DIR" || exit 1
|
|
|
|
# Check if ffprobe is available
|
|
if ! command -v ffprobe &> /dev/null; then
|
|
echo "Error: ffprobe is not installed. Please install ffmpeg."
|
|
exit 1
|
|
fi
|
|
|
|
# Function to get video duration in h:mm format
|
|
get_duration() {
|
|
local file="$1"
|
|
local seconds=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
|
|
if [[ -n "$seconds" ]]; then
|
|
local hours=$((${seconds%.*} / 3600))
|
|
local minutes=$(((${seconds%.*} % 3600) / 60))
|
|
printf "%d:%02d" "$hours" "$minutes"
|
|
else
|
|
echo "0:00"
|
|
fi
|
|
}
|
|
|
|
# Function to detect orientation
|
|
get_orientation() {
|
|
local file="$1"
|
|
local width=$(ffprobe -v error -select_streams v:0 -show_entries stream=width -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
|
|
local height=$(ffprobe -v error -select_streams v:0 -show_entries stream=height -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
|
|
|
|
if [[ -n "$width" ]] && [[ -n "$height" ]]; then
|
|
if [[ $height -gt $width ]]; then
|
|
echo "V"
|
|
else
|
|
echo "H"
|
|
fi
|
|
else
|
|
echo "H"
|
|
fi
|
|
}
|
|
|
|
# Function to detect video quality
|
|
get_quality() {
|
|
local file="$1"
|
|
local height=$(ffprobe -v error -select_streams v:0 -show_entries stream=height -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
|
|
|
|
if [[ -n "$height" ]]; then
|
|
if [[ $height -ge 2160 ]]; then
|
|
echo "4K"
|
|
elif [[ $height -ge 1440 ]]; then
|
|
echo "1440p"
|
|
elif [[ $height -ge 1080 ]]; then
|
|
echo "1080p"
|
|
elif [[ $height -ge 720 ]]; then
|
|
echo "720p"
|
|
elif [[ $height -ge 480 ]]; then
|
|
echo "480p"
|
|
else
|
|
echo "SD"
|
|
fi
|
|
else
|
|
echo "720p"
|
|
fi
|
|
}
|
|
|
|
# Function to check if file is already H.265/HEVC encoded
|
|
is_hevc() {
|
|
local file="$1"
|
|
local codec=$(ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
|
|
[[ "$codec" == "hevc" ]] || [[ "$codec" == "h265" ]]
|
|
}
|
|
|
|
# Function to check if filename has [E] encoded flag
|
|
has_encoded_flag() {
|
|
local filename="$1"
|
|
[[ "$filename" =~ \[E\] ]]
|
|
}
|
|
|
|
# Function to extract and format date from filename
|
|
extract_date() {
|
|
local filename="$1"
|
|
local date=""
|
|
|
|
# Try YY.MM.DD format (e.g., 25.11.19)
|
|
if [[ "$filename" =~ ([0-9]{2})\.([0-9]{2})\.([0-9]{2}) ]]; then
|
|
date="${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-20${BASH_REMATCH[1]}"
|
|
# Try YYYY.MM.DD format
|
|
elif [[ "$filename" =~ (20[0-9]{2})\.([0-9]{2})\.([0-9]{2}) ]]; then
|
|
date="${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-${BASH_REMATCH[1]}"
|
|
# Try YYYYMMDD format
|
|
elif [[ "$filename" =~ (20[0-9]{2})([0-9]{2})([0-9]{2}) ]]; then
|
|
date="${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-${BASH_REMATCH[1]}"
|
|
# Try DD-MM-YYYY format
|
|
elif [[ "$filename" =~ ([0-9]{2})-([0-9]{2})-(20[0-9]{2}) ]]; then
|
|
date="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}"
|
|
# Try (DD.MM.YYYY) format
|
|
elif [[ "$filename" =~ \(([0-9]{2})\.([0-9]{2})\.([0-9]{4})\) ]]; then
|
|
date="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}"
|
|
fi
|
|
|
|
echo "$date"
|
|
}
|
|
|
|
# Function to clean and standardize filename
|
|
clean_filename() {
|
|
local name="$1"
|
|
local studio="$2"
|
|
|
|
# Remove common release group tags and patterns (case insensitive) but preserve quality info
|
|
name=$(echo "$name" | sed -E 's/\.(XXX|[XC]|MP4|WEB|HD)\..*//gi')
|
|
name=$(echo "$name" | sed -E 's/ (XXX|WEB|HD).*//gi')
|
|
|
|
# Remove existing metadata tags
|
|
name=$(echo "$name" | sed -E 's/ \[[0-9]+:[0-9]+\]//g')
|
|
name=$(echo "$name" | sed -E 's/ \[[HV]\]//g')
|
|
name=$(echo "$name" | sed -E 's/ \[[0-9]{2}-[0-9]{2}-[0-9]{4}\]//g')
|
|
name=$(echo "$name" | sed -E 's/ \[(4K|1440p|1080p|720p|480p|SD)\]//g')
|
|
name=$(echo "$name" | sed -E 's/ \[E\]//g')
|
|
|
|
# Remove " rq" suffix (release quality tag)
|
|
name=$(echo "$name" | sed -E 's/ rq$//gi')
|
|
|
|
# Remove quality tags from title but preserve them for later
|
|
name=$(echo "$name" | sed -E 's/\.(4K|2160p|1440p|1080p|720p|480p)//gi')
|
|
name=$(echo "$name" | sed -E 's/ (4K|2160p|1440p|1080p|720p|480p)//gi')
|
|
name=$(echo "$name" | sed -E 's/_720p$//gi')
|
|
|
|
# Remove dates from the main title
|
|
name=$(echo "$name" | sed -E 's/\.?[0-9]{2}\.[0-9]{2}\.[0-9]{2}\.?//g')
|
|
name=$(echo "$name" | sed -E 's/\.?(20[0-9]{2})\.[0-9]{2}\.[0-9]{2}\.?//g')
|
|
name=$(echo "$name" | sed -E 's/(20[0-9]{2})[0-9]{6}//g')
|
|
name=$(echo "$name" | sed -E 's/[0-9]{2}-[0-9]{2}-(20[0-9]{2})//g')
|
|
name=$(echo "$name" | sed -E 's/\([0-9]{2}\.[0-9]{2}\.[0-9]{4}\)//g')
|
|
|
|
# Special handling for OnlyFans
|
|
if [[ "$studio" == "OnlyFans" ]]; then
|
|
# Remove "onlyfans" prefix (case insensitive)
|
|
name=$(echo "$name" | sed -E 's/^[Oo]nly[Ff]ans\.?//g')
|
|
name=$(echo "$name" | sed -E 's/^[Oo]nly[Ff]ans //g')
|
|
|
|
# Remove year prefix/suffix like "2025" or " 2025 "
|
|
name=$(echo "$name" | sed -E 's/^20[0-9]{2}\.?//g')
|
|
name=$(echo "$name" | sed -E 's/^20[0-9]{2} //g')
|
|
name=$(echo "$name" | sed -E 's/ 20[0-9]{2} / /g')
|
|
|
|
# Remove "xxx" suffix
|
|
name=$(echo "$name" | sed -E 's/ xxx$//gi')
|
|
|
|
# Don't extract if already has the pattern - just return it
|
|
# This prevents adding extra dashes when re-processing
|
|
fi
|
|
|
|
# Remove studio name prefix (case insensitive)
|
|
name=$(echo "$name" | sed -E "s/^${studio}\.//gi")
|
|
name=$(echo "$name" | sed -E "s/^${studio} //gi")
|
|
|
|
# Replace dots and underscores with spaces
|
|
name=$(echo "$name" | tr '._' ' ')
|
|
|
|
# Remove multiple spaces
|
|
name=$(echo "$name" | sed -E 's/ +/ /g')
|
|
|
|
# Trim leading/trailing spaces and dashes
|
|
name=$(echo "$name" | sed -E 's/^[\ -]+| +$//g')
|
|
|
|
# Capitalize first letter of each word for better readability
|
|
name=$(echo "$name" | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1')
|
|
|
|
echo "$name"
|
|
}
|
|
|
|
# ===========================================
|
|
# INBOX PROCESSING - Sort files to correct directories
|
|
# ===========================================
|
|
echo "=== Processing Inbox Directory ==="
|
|
if [[ -d "$INBOX_DIR" ]]; then
|
|
# Search recursively for mp4 files (handles release group folders)
|
|
inbox_count=$(find "$INBOX_DIR" -type f -name "*.mp4" 2>/dev/null | wc -l)
|
|
if [[ $inbox_count -gt 0 ]]; then
|
|
echo "Found $inbox_count file(s) in inbox"
|
|
|
|
find "$INBOX_DIR" -type f -name "*.mp4" | while read -r file; do
|
|
filename=$(basename "$file")
|
|
echo "Processing: $filename"
|
|
|
|
# Determine destination based on filename patterns
|
|
destination=""
|
|
|
|
# Check if file is inside a digest output folder (Clips - * or Scenes - *)
|
|
parent_dir=$(basename "$(dirname "$file")")
|
|
if [[ "$parent_dir" == Clips\ -\ * ]] || [[ "$parent_dir" == Scenes\ -\ * ]]; then
|
|
destination="$GIFS_DIR/$parent_dir"
|
|
echo " -> GIFs/$parent_dir (digest output)"
|
|
|
|
# Check for OnlyFans content (treated as a regular studio)
|
|
elif [[ "$filename" =~ ^[Oo]nly[Ff]ans ]] || [[ "$filename" =~ [Oo]nly[Ff]ans\.? ]]; then
|
|
destination="$ROOT_DIR/OnlyFans"
|
|
echo " -> Studios/OnlyFans (detected OnlyFans pattern)"
|
|
|
|
# Check for known GIF/clip patterns (short duration indicator or known creators)
|
|
# Files with [Xs] duration tag are likely GIFs
|
|
elif [[ "$filename" =~ \[[0-9]+s\] ]]; then
|
|
# Extract creator name (first part before any separator)
|
|
if [[ "$filename" =~ ^([A-Za-z0-9_-]+) ]]; then
|
|
creator="${BASH_REMATCH[1]}"
|
|
# Check if creator directory exists in gifs
|
|
if [[ -d "$GIFS_DIR/$creator" ]]; then
|
|
destination="$GIFS_DIR/$creator"
|
|
echo " -> GIFs/$creator (detected short clip for existing creator)"
|
|
else
|
|
destination="$GIFS_DIR"
|
|
echo " -> GIFs (detected short clip)"
|
|
fi
|
|
else
|
|
destination="$GIFS_DIR"
|
|
echo " -> GIFs (detected short clip)"
|
|
fi
|
|
|
|
# Check file duration for potential GIF content (under 2 minutes)
|
|
else
|
|
duration_sec=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null | cut -d. -f1)
|
|
if [[ -n "$duration_sec" ]] && [[ "$duration_sec" -lt 120 ]]; then
|
|
# Short file - likely a GIF/clip
|
|
# Try to match to existing creator
|
|
if [[ "$filename" =~ ^([A-Za-z0-9_-]+) ]]; then
|
|
creator="${BASH_REMATCH[1]}"
|
|
if [[ -d "$GIFS_DIR/$creator" ]]; then
|
|
destination="$GIFS_DIR/$creator"
|
|
echo " -> GIFs/$creator (short file, matched creator)"
|
|
else
|
|
destination="$GIFS_DIR"
|
|
echo " -> GIFs (short file < 2min)"
|
|
fi
|
|
else
|
|
destination="$GIFS_DIR"
|
|
echo " -> GIFs (short file < 2min)"
|
|
fi
|
|
else
|
|
# Regular video - goes to studios
|
|
# Try to extract studio from filename
|
|
if [[ "$filename" =~ ^([A-Za-z0-9]+)[\.\-\ ] ]]; then
|
|
studio="${BASH_REMATCH[1]}"
|
|
destination="$ROOT_DIR/$studio"
|
|
mkdir -p "$destination"
|
|
echo " -> Studios/$studio"
|
|
else
|
|
destination="$ROOT_DIR"
|
|
echo " -> Studios (root)"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Copy file to destination (non-destructive - keeps original in inbox)
|
|
if [[ -n "$destination" ]]; then
|
|
mkdir -p "$destination"
|
|
cp "$file" "$destination/"
|
|
echo " Copied to: $destination/"
|
|
fi
|
|
done
|
|
|
|
# Note: We intentionally do NOT clean up the inbox directory
|
|
# Files remain in inbox until manually deleted by user
|
|
echo "Inbox files copied (originals retained in inbox)"
|
|
else
|
|
echo "Inbox is empty"
|
|
fi
|
|
else
|
|
echo "Inbox directory not found, skipping"
|
|
fi
|
|
echo ""
|
|
|
|
# Find all MP4 files (including root level)
|
|
find . -mindepth 1 -type f -name "*.mp4" | while read -r file; do
|
|
# Skip files in excluded directories
|
|
if [[ "$file" =~ /scripts/ ]] || [[ "$file" =~ /spankbang/ ]] || [[ "$file" =~ /gifs/ ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Skip compilation files (files with " - Compilation [H]" or " - Compilation [V]" in name)
|
|
filename=$(basename "$file")
|
|
if [[ "$filename" =~ " - Compilation [HV]].mp4"$ ]]; then
|
|
continue
|
|
fi
|
|
|
|
dir=$(dirname "$file")
|
|
depth=$(echo "$dir" | tr -cd '/' | wc -c)
|
|
dirname=$(basename "$dir")
|
|
filename=$(basename "$file")
|
|
|
|
# SKIP if file already has proper [H:MM] [quality] [H/V] format and is in correct directory
|
|
# This check happens BEFORE any ffprobe calls for efficiency
|
|
# [E] flag is optional - files may or may not have been re-encoded yet
|
|
if [[ "$filename" =~ \[[0-9]+:[0-9]+\].*\[(4K|1440p|1080p|720p|480p|SD)\].*(\[E\].*)?(\[[HV]\])\.mp4$ ]]; then
|
|
# File has all metadata tags - check if it's in correct studio folder
|
|
if [[ $depth -eq 1 ]]; then
|
|
# Already in a studio folder with proper tags, skip
|
|
continue
|
|
fi
|
|
# Check if in OnlyFans performer subdirectory
|
|
parent_dir=$(dirname "$dir")
|
|
parent_name=$(basename "$parent_dir")
|
|
if [[ "$parent_name" == "OnlyFans" ]] && [[ $depth -eq 2 ]]; then
|
|
# In OnlyFans performer subdirectory with proper tags, skip
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
# Check if file needs metadata update
|
|
needs_update=false
|
|
needs_rename=false
|
|
|
|
# Check if filename already has metadata tags (excluding [E] which is optional)
|
|
if [[ ! "$filename" =~ \[[0-9]+:[0-9]+\] ]] || [[ ! "$filename" =~ \[[HV]\] ]] || [[ ! "$filename" =~ \[(4K|1440p|1080p|720p|480p|SD)\] ]]; then
|
|
needs_rename=true
|
|
fi
|
|
|
|
# Check if filename needs cleaning (has periods, underscores, or dates in title)
|
|
# Note: We exclude ".mp4" from period check
|
|
name_without_ext="${filename%.mp4}"
|
|
if [[ "$name_without_ext" =~ \. ]] || [[ "$name_without_ext" =~ _ ]] || [[ "$filename" =~ [0-9]{2}\.[0-9]{2}\.[0-9]{2} ]] || [[ "$filename" =~ (20[0-9]{2})[0-9]{6} ]] || [[ "$filename" =~ (^|[^0-9])(20[0-9]{2})([^0-9]) ]] || [[ "$filename" =~ XXX ]] || [[ "$filename" =~ 1080p ]] || [[ "$filename" =~ 2160p ]]; then
|
|
needs_rename=true
|
|
fi
|
|
|
|
# Extract studio name
|
|
studio=""
|
|
|
|
# If file is in root, try to extract studio from filename
|
|
if [[ "$dir" == "." ]]; then
|
|
if [[ "$filename" =~ ^([A-Za-z0-9]+)\. ]] || [[ "$filename" =~ ^([A-Za-z0-9]+)\ -\ ]]; then
|
|
studio="${BASH_REMATCH[1]}"
|
|
else
|
|
studio="Unknown"
|
|
fi
|
|
needs_update=true # Files in root always need to be moved
|
|
else
|
|
# Check if already in a performer subdirectory under OnlyFans
|
|
parent_dir=$(dirname "$dir")
|
|
parent_name=$(basename "$parent_dir")
|
|
|
|
# If parent is OnlyFans and current dir is a performer folder, skip
|
|
if [[ "$parent_name" == "OnlyFans" ]] && [[ $depth -eq 2 ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Extract from directory name
|
|
if [[ "$dirname" =~ ^([A-Za-z0-9]+)\. ]]; then
|
|
studio="${BASH_REMATCH[1]}"
|
|
elif [[ "$dirname" =~ ^([A-Za-z0-9]+)\ -\ ]]; then
|
|
studio="${BASH_REMATCH[1]}"
|
|
else
|
|
studio="$dirname"
|
|
fi
|
|
|
|
# Check if file is in wrong directory
|
|
if [[ $depth -eq 1 ]] && [[ "$dirname" == "$studio" ]]; then
|
|
# File is already in correct studio folder, check if it needs renaming
|
|
if [[ "$needs_rename" == true ]]; then
|
|
needs_update=true
|
|
fi
|
|
else
|
|
# File needs to be moved
|
|
needs_update=true
|
|
fi
|
|
fi
|
|
|
|
# Process file if it needs update or rename
|
|
if [[ "$needs_update" == true ]] || [[ "$needs_rename" == true ]]; then
|
|
echo "Analyzing: $file"
|
|
duration=$(get_duration "$file")
|
|
orientation=$(get_orientation "$file")
|
|
quality=$(get_quality "$file")
|
|
date=$(extract_date "$filename")
|
|
|
|
# Create studio directory if it doesn't exist
|
|
if [[ -n "$studio" ]]; then
|
|
mkdir -p "$ROOT_DIR/$studio"
|
|
|
|
# Clean and standardize filename
|
|
clean_name=$(clean_filename "${filename%.*}" "$studio")
|
|
ext="${filename##*.}"
|
|
|
|
# For OnlyFans, ensure proper format: OnlyFans - Name - Description
|
|
if [[ "$studio" == "OnlyFans" ]]; then
|
|
# Check if clean_name already has " - Name - Description" pattern
|
|
if [[ "$clean_name" =~ ^([A-Z][a-z]+([\ ][A-Z][a-z]+){0,3})[\ ]-[\ ](.+)$ ]]; then
|
|
# Already has the proper format, just add OnlyFans prefix
|
|
performer="${BASH_REMATCH[1]}"
|
|
description="${BASH_REMATCH[3]}"
|
|
new_filename="OnlyFans - ${performer} - ${description}"
|
|
# Try to extract performer name (typically first 1-3 capitalized words)
|
|
elif [[ "$clean_name" =~ ^([A-Z][a-z]+([\ ][A-Z][a-z]+){0,2})([\ ].+)$ ]]; then
|
|
# Has "Name Description" pattern - add separator
|
|
performer="${BASH_REMATCH[1]}"
|
|
description="${BASH_REMATCH[3]}"
|
|
description=$(echo "$description" | sed -E 's/^ +//g')
|
|
new_filename="OnlyFans - ${performer} - ${description}"
|
|
else
|
|
# Can't extract name, just add OnlyFans prefix
|
|
# Clean up any leading dashes or spaces
|
|
clean_name=$(echo "$clean_name" | sed -E 's/^[\ -]+//g')
|
|
if [[ -n "$clean_name" ]]; then
|
|
new_filename="OnlyFans - ${clean_name}"
|
|
else
|
|
new_filename="OnlyFans"
|
|
fi
|
|
fi
|
|
# For other studios with performer names in title
|
|
elif [[ "$studio" =~ ^(IntimatePOV|LegalPorno|AccidentalGangbang|18Lust|BlackedRaw|PublicBang|OnlyTarts|Wifey)$ ]]; then
|
|
# Try to intelligently separate performer from title
|
|
# Look for common title indicator words
|
|
if [[ "$clean_name" =~ ^([A-Z][a-z]+([\ ][A-Z][a-z]+){0,3})([\ ](Is|A|The|With|For|On|Of|To|In|Her|Your|My|Lets|Pretend|Seducing|Doubling|Naked|Morning|Sub|Likes|Over).+)$ ]]; then
|
|
performer="${BASH_REMATCH[1]}"
|
|
title="${BASH_REMATCH[3]}"
|
|
title=$(echo "$title" | sed -E 's/^ +//g')
|
|
new_filename="${studio} - ${performer} - ${title}"
|
|
else
|
|
# No clear separator, just use studio and clean name
|
|
# Clean up any leading dashes or spaces
|
|
clean_name=$(echo "$clean_name" | sed -E 's/^[\ -]+//g')
|
|
if [[ -n "$clean_name" ]]; then
|
|
new_filename="${studio} - ${clean_name}"
|
|
else
|
|
new_filename="${studio}"
|
|
fi
|
|
fi
|
|
else
|
|
# For unknown studios, clean up leading dashes/spaces
|
|
clean_name=$(echo "$clean_name" | sed -E 's/^[\ -]+//g')
|
|
if [[ -n "$clean_name" ]]; then
|
|
new_filename="${clean_name}"
|
|
else
|
|
new_filename="${studio}"
|
|
fi
|
|
fi
|
|
|
|
# Determine if file should have [E] encoded flag
|
|
# Preserve existing [E] flag or add if video is HEVC encoded
|
|
encoded_flag=""
|
|
if has_encoded_flag "$filename"; then
|
|
encoded_flag=" [E]"
|
|
elif is_hevc "$file"; then
|
|
encoded_flag=" [E]"
|
|
echo " Adding [E] flag: Already HEVC encoded"
|
|
fi
|
|
|
|
# Add metadata tags
|
|
# Format: [date] [duration] [quality] [E] [orientation]
|
|
if [[ -n "$date" ]]; then
|
|
new_filename="${new_filename} [${date}] [${duration}] [${quality}]${encoded_flag} [${orientation}].${ext}"
|
|
else
|
|
new_filename="${new_filename} [${duration}] [${quality}]${encoded_flag} [${orientation}].${ext}"
|
|
fi
|
|
|
|
# Clean up any multiple dashes that may have been created
|
|
new_filename=$(echo "$new_filename" | sed -E 's/ - - - / - /g' | sed -E 's/ - - / - /g')
|
|
|
|
# Set target path (all studios use ROOT_DIR)
|
|
target_path="$ROOT_DIR/$studio/$new_filename"
|
|
|
|
# Only move/rename if target is different from source
|
|
if [[ "$file" != "./$studio/$new_filename" ]]; then
|
|
echo "Processing: $file -> $studio/$new_filename"
|
|
mv "$file" "$target_path"
|
|
fi
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "Done organizing studio files!"
|
|
echo ""
|
|
|
|
echo "=== Organizing GIFs folder ==="
|
|
|
|
# Function to get duration in seconds for gifs
|
|
get_duration_seconds() {
|
|
local file="$1"
|
|
local seconds=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
|
|
if [[ -n "$seconds" ]]; then
|
|
printf "%.0f" "$seconds"
|
|
else
|
|
echo "0"
|
|
fi
|
|
}
|
|
|
|
if [[ -d "$GIFS_DIR" ]]; then
|
|
cd "$GIFS_DIR" || exit 1
|
|
|
|
# Process each creator directory
|
|
for creator_dir in */; do
|
|
if [[ -d "$creator_dir" ]]; then
|
|
creator_name="${creator_dir%/}"
|
|
echo "Processing: $creator_name"
|
|
|
|
# Create horizontal/vertical subdirs if they don't exist
|
|
mkdir -p "$creator_name/horizontal"
|
|
mkdir -p "$creator_name/vertical"
|
|
|
|
# Process ALL mp4 files in creator directory (root and subdirs)
|
|
find "$creator_name" -type f -name "*.mp4" | while read -r file; do
|
|
filename=$(basename "$file")
|
|
file_dir=$(dirname "$file")
|
|
|
|
# SKIP compilation files - they should stay in the creator root directory
|
|
# Match ANY file with " - Compilation " in the name (whether freshly created or already tagged)
|
|
if [[ "$filename" == *" - Compilation "* ]]; then
|
|
# This is a generated compilation file
|
|
# Move it to creator root if it's in a subdirectory
|
|
if [[ "$file_dir" != "$creator_name" ]]; then
|
|
echo " Moving compilation to root: $filename"
|
|
mv "$file" "$creator_name/$filename"
|
|
fi
|
|
continue
|
|
fi
|
|
|
|
# SKIP if file already has proper [Xs] [quality] [H/V] format
|
|
# This check happens BEFORE any ffprobe calls for efficiency
|
|
# [E] flag is optional - files may or may not have been re-encoded yet
|
|
if [[ "$filename" =~ \[[0-9]+s\].*\[(4K|1440p|1080p|720p|480p|SD)\].*(\[E\].*)?(\[[HV]\])\.mp4$ ]]; then
|
|
# File is already fully processed
|
|
# Just check if it's in the correct H/V subdirectory
|
|
if [[ "$filename" =~ \[H\]\.mp4$ ]] && [[ "$file_dir" == *"/horizontal" ]]; then
|
|
continue # Already in correct place
|
|
elif [[ "$filename" =~ \[V\]\.mp4$ ]] && [[ "$file_dir" == *"/vertical" ]]; then
|
|
continue # Already in correct place
|
|
fi
|
|
# Move to correct subdirectory without re-analyzing
|
|
if [[ "$filename" =~ \[H\]\.mp4$ ]]; then
|
|
target_dir="$creator_name/horizontal"
|
|
else
|
|
target_dir="$creator_name/vertical"
|
|
fi
|
|
if [[ "$file" != "$target_dir/$filename" ]]; then
|
|
echo " Moving: $filename -> $target_dir/"
|
|
mv "$file" "$target_dir/$filename"
|
|
fi
|
|
continue
|
|
fi
|
|
|
|
# File needs processing - now run ffprobe
|
|
echo " Analyzing: $filename"
|
|
orientation=$(get_orientation "$file")
|
|
quality=$(get_quality "$file")
|
|
duration_sec=$(get_duration_seconds "$file")
|
|
|
|
# Clean filename - remove existing tags and extension
|
|
clean_name="${filename%.*}"
|
|
clean_name=$(echo "$clean_name" | sed -E 's/ \[[0-9]+:[0-9]+\]//g')
|
|
clean_name=$(echo "$clean_name" | sed -E 's/ \[[0-9]+s\]//g')
|
|
clean_name=$(echo "$clean_name" | sed -E 's/ \[[HV]\]//g')
|
|
clean_name=$(echo "$clean_name" | sed -E 's/ \[(4K|1440p|1080p|720p|480p|SD)\]//g')
|
|
clean_name=$(echo "$clean_name" | sed -E 's/ \[E\]//g')
|
|
|
|
# Determine if file should have [E] encoded flag
|
|
encoded_flag=""
|
|
if has_encoded_flag "$filename"; then
|
|
encoded_flag=" [E]"
|
|
elif is_hevc "$file"; then
|
|
encoded_flag=" [E]"
|
|
echo " Adding [E] flag: Already HEVC encoded"
|
|
fi
|
|
|
|
# Build new filename with metadata
|
|
# Format: [Xs] [quality] [E] [orientation]
|
|
new_filename="${clean_name} [${duration_sec}s] [${quality}]${encoded_flag} [${orientation}].mp4"
|
|
|
|
# Determine target directory based on orientation
|
|
if [[ "$orientation" == "H" ]]; then
|
|
target_dir="$creator_name/horizontal"
|
|
else
|
|
target_dir="$creator_name/vertical"
|
|
fi
|
|
|
|
# Only move/rename if needed
|
|
if [[ "$file" != "$target_dir/$new_filename" ]]; then
|
|
echo " -> $target_dir/$(basename "$new_filename")"
|
|
mv "$file" "$target_dir/$new_filename"
|
|
fi
|
|
done
|
|
|
|
# Clean up empty subdirectories (like old square folders if emptied)
|
|
find "$creator_name" -mindepth 1 -type d -empty -delete 2>/dev/null
|
|
fi
|
|
done
|
|
|
|
cd "$ROOT_DIR" || exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo "Cleaning up old directories..."
|
|
|
|
# Remove the now-empty source directories that match typical release naming patterns
|
|
find . -mindepth 1 -maxdepth 1 -type d \( -name "*XXX*" -o -name "*[XC]" -o -name "*.MP4-*" \) -exec rm -rf {} + 2>/dev/null
|
|
|
|
# Remove any remaining empty directories
|
|
find . -mindepth 1 -type d -empty -delete 2>/dev/null
|
|
|
|
echo ""
|
|
echo "Complete!"
|