#!/bin/bash # Parse arguments DRY_RUN=false INPUT_DIR="" OUTPUT_DIR="" while [[ $# -gt 0 ]]; do case $1 in --dry-run|-n) DRY_RUN=true shift ;; --input|-i) INPUT_DIR="$2" shift 2 ;; --output|-o) OUTPUT_DIR="$2" shift 2 ;; --help|-h) echo "Usage: $0 --input DIR --output DIR [OPTIONS]" echo "" echo "Required:" echo " --input, -i DIR Input directory containing videos" echo " --output, -o DIR Output directory for organized videos" echo "" echo "Options:" echo " --dry-run, -n Preview changes without moving files" echo " --help, -h Show this help message" exit 0 ;; *) echo "Unknown option: $1" echo "Use --help for usage information" exit 1 ;; esac done # Validate required arguments if [[ -z "$INPUT_DIR" ]]; then echo "Error: --input directory is required" echo "Use --help for usage information" exit 1 fi if [[ -z "$OUTPUT_DIR" ]]; then echo "Error: --output directory is required" echo "Use --help for usage information" exit 1 fi # Check if input directory exists if [[ ! -d "$INPUT_DIR" ]]; then echo "Error: Input directory '$INPUT_DIR' does not exist" exit 1 fi # Check if exiftool is installed if ! command -v exiftool &> /dev/null; then echo "Error: exiftool is not installed. Please install it first." echo " Ubuntu/Debian: sudo apt-get install libimage-exiftool-perl" echo " macOS: brew install exiftool" exit 1 fi # Create output directory (only if not dry-run) if [[ "$DRY_RUN" == false ]]; then mkdir -p "$OUTPUT_DIR" fi # Counters processed=0 skipped=0 failed=0 if [[ "$DRY_RUN" == true ]]; then echo "🔍 DRY RUN MODE - No files will be moved" fi echo "Starting video organization..." echo "Input directory: $INPUT_DIR" echo "Output directory: $OUTPUT_DIR" echo "" # Process each video # Using -iname for case-insensitive matching (matches .mp4, .MP4, .Mp4, etc.) while IFS= read -r video; do echo "Processing: $(basename "$video")" # Extract creation date (YYYYMMDD) creation_date=$(exiftool -MediaCreateDate -d "%Y%m%d" -s3 "$video" 2>/dev/null | head -n 1 | tr -d ' ') # Check if date was extracted successfully if [[ -z "$creation_date" ]] || [[ ! "$creation_date" =~ ^[0-9]{8}$ ]]; then echo " ⚠ Warning: Could not extract valid date, moving to Unknown folder" target_dir="$OUTPUT_DIR/Unknown" destination="$target_dir/$(basename "$video")" # Check if destination file already exists if [[ -f "$destination" ]]; then # Add timestamp to avoid overwrite filename=$(basename "$video") extension="${filename##*.}" basename_no_ext="${filename%.*}" destination="$target_dir/${basename_no_ext}_$(date +%s).$extension" echo " ⚠ File exists, renaming to: $(basename "$destination")" fi if [[ "$DRY_RUN" == true ]]; then echo " → Would move to: Unknown/$(basename "$destination")" else mkdir -p "$target_dir" if mv "$video" "$destination" 2>/dev/null; then echo " ✓ Moved to: Unknown/" else echo " ✗ Failed to move file" failed=$((failed + 1)) continue fi fi skipped=$((skipped + 1)) continue fi # Extract year, month, day year="${creation_date:0:4}" month="${creation_date:4:2}" day="${creation_date:6:2}" # Create subdirectories (YYYY/MM/DD) target_dir="$OUTPUT_DIR/$year/$month/$day" # Check if destination file already exists destination="$target_dir/$(basename "$video")" if [[ -f "$destination" ]]; then # Add timestamp to avoid overwrite filename=$(basename "$video") extension="${filename##*.}" basename_no_ext="${filename%.*}" destination="$target_dir/${basename_no_ext}_$(date +%s).$extension" echo " ⚠ File exists, renaming to: $(basename "$destination")" fi if [[ "$DRY_RUN" == true ]]; then # Dry run: just show what would happen echo " → Would move to: $year/$month/$day/$(basename "$destination")" processed=$((processed + 1)) else # Actually perform the move mkdir -p "$target_dir" if mv "$video" "$destination" 2>/dev/null; then echo " ✓ Moved to: $year/$month/$day/" processed=$((processed + 1)) else echo " ✗ Failed to move file" failed=$((failed + 1)) fi fi done < <(find "$INPUT_DIR" -type f \( -iname "*.mp4" -o -iname "*.mov" -o -iname "*.mkv" -o -iname "*.avi" -o -iname "*.wmv" -o -iname "*.flv" -o -iname "*.webm" \)) echo "" if [[ "$DRY_RUN" == true ]]; then echo "DRY RUN Summary:" echo " Would process: $processed" echo " Would move to Unknown: $skipped" else echo "Summary:" echo " Processed: $processed" echo " Moved to Unknown: $skipped" echo " Failed: $failed" fi