move_videos.sh 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #!/bin/sh
  2. # POSIX-compliant script to move video files preserving directory structure
  3. # Defaults
  4. SOURCE_DIR=""
  5. DEST_DIR=""
  6. DRY_RUN=false
  7. # Video extensions (case insensitive matching)
  8. VIDEO_EXTS="mp4 mov avi mkv flv wmv m4v 3gp webm"
  9. # Help function
  10. show_help() {
  11. echo "Usage: $0 [options] source_directory destination_directory"
  12. echo
  13. echo "Options:"
  14. echo " -n, --dry-run Show what would be moved without actually doing it"
  15. echo " -h, --help Show this help message"
  16. echo
  17. echo "Example:"
  18. echo " $0 ~/Pictures ~/videos"
  19. echo " $0 -n ~/PhoneDCIM ~/backup/videos"
  20. }
  21. # Parse arguments
  22. while [ $# -gt 0 ]; do
  23. case "$1" in
  24. -n|--dry-run)
  25. DRY_RUN=true
  26. shift
  27. ;;
  28. -h|--help)
  29. show_help
  30. exit 0
  31. ;;
  32. -*)
  33. echo "Error: Unknown option $1" >&2
  34. show_help
  35. exit 1
  36. ;;
  37. *)
  38. if [ -z "$SOURCE_DIR" ]; then
  39. SOURCE_DIR="$1"
  40. elif [ -z "$DEST_DIR" ]; then
  41. DEST_DIR="$1"
  42. else
  43. echo "Error: Too many arguments" >&2
  44. show_help
  45. exit 1
  46. fi
  47. shift
  48. ;;
  49. esac
  50. done
  51. # Validate parameters
  52. if [ -z "$SOURCE_DIR" ] || [ -z "$DEST_DIR" ]; then
  53. echo "Error: Source and destination directories are required" >&2
  54. show_help
  55. exit 1
  56. fi
  57. if [ ! -d "$SOURCE_DIR" ]; then
  58. echo "Error: Source directory does not exist: $SOURCE_DIR" >&2
  59. exit 1
  60. fi
  61. # Create destination directory if it doesn't exist
  62. if [ "$DRY_RUN" = false ]; then
  63. mkdir -p "$DEST_DIR"
  64. fi
  65. echo "Source directory: $SOURCE_DIR"
  66. echo "Destination directory: $EST_DIR"
  67. echo "Mode: $([ "$DRY_RUN" = true ] && echo "Dry run (simulation)" || echo "Real execution")"
  68. echo
  69. # Build find command for case insensitive matching
  70. find "$SOURCE_DIR" -type f | while IFS= read -r file; do
  71. # Check if file has a video extension (case insensitive)
  72. ext=$(echo "$file" | tr '[:upper:]' '[:lower:]' | awk -F. '{print $NF}')
  73. found=false
  74. for video_ext in $VIDEO_EXTS; do
  75. if [ "$ext" = "$video_ext" ]; then
  76. found=true
  77. break
  78. fi
  79. done
  80. [ "$found" = false ] && continue
  81. # Get relative path
  82. relative_path="${file#$SOURCE_DIR/}"
  83. # Determine destination path
  84. dest_file="$DEST_DIR/$relative_path"
  85. dest_dir=$(dirname "$dest_file")
  86. if [ "$DRY_RUN" = true ]; then
  87. echo "[DRY RUN] Would move: $file"
  88. echo " to: $dest_file"
  89. else
  90. # Create destination directory if needed
  91. mkdir -p "$dest_dir"
  92. # Move the file
  93. if mv -v "$file" "$dest_file"; then
  94. echo "Moved: $file -> $dest_file"
  95. else
  96. echo "Error moving: $file" >&2
  97. fi
  98. fi
  99. done
  100. echo
  101. echo "Operation completed."
  102. if [ "$DRY_RUN" = true ]; then
  103. echo "NOTE: This was a dry run - no files were actually moved"
  104. fi