Advertisement
MestreLion

matchsubtitles - rename subtitles to match video files

Aug 27th, 2011
295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 4.37 KB | None | 0 0
  1. #!/bin/bash
  2. #
  3. # Wrapper for matchsubtitles, suitable for Nautilus Scripts
  4. #
  5. # Copyright (C) 2011 Rodrigo Silva (MestreLion) <[email protected]>
  6. # License: GPLv3 or later, at your choice. See <http://www.gnu.org/licenses/gpl>
  7.  
  8. error=$(matchsubtitles --undo ".matchsubtitles_undo.sh" --run -- "$@" 2>&1 >/dev/null)
  9.  
  10. [[ "$error" ]] && zenity --error --title "Match subtitles" --no-wrap --text "${error//&/&amp;}"
  11.  
  12.  
  13. #!/bin/bash
  14. #
  15. # Rename subtitles (.srt files) to match the given video files
  16. #
  17. # Copyright (C) 2011 Rodrigo Silva (MestreLion) <[email protected]>
  18. # License: GPLv3 or later, at your choice. See <http://www.gnu.org/licenses/gpl>
  19. #
  20. # TODO: Sort files array
  21. # TODO: Support for multiple language subtitles ( *.xx.srt )
  22. # FIXME: Decent usage explaining options and behaviour
  23.  
  24. self="${0##*/}"
  25.  
  26. fatal() {
  27.     local msg="$1"
  28.     [[ "$msg" ]] && printf "%s: %s\nTry '%s --help' for more information\n" \
  29.                            "$self" "$msg" "$self" >&2
  30.     exit 1
  31. }
  32. usage() {
  33. cat << USAGEDOC
  34. Rename subtitles (.srt files) to match the given video files
  35.  
  36. Usage: $self [--undo FILE] [--verbose] [--run] [--] [FILE|DIR]...
  37.  
  38. Options:
  39. --undo FILE - Create an undo script to revert the renaming. Run ./FILE to revert
  40. --run       - If not used, will not actually rename subtitles, only show what will be done
  41.  
  42. Video files are *.avi, *.mkv, *.mpg and *.mpeg. All other files are ignored
  43. Files that already have a matching subtitle and subtitles that already have a matching video will be ignored
  44. For desired results, files in same dir must be given in alphabetical order (use globs for that).
  45. Example: $self ~/Videos/Lost /shared/csi/miami_s1* '/movies/star wars'
  46. USAGEDOC
  47. exit
  48. }
  49.  
  50. printundo() {
  51.    
  52.     local header="$1"
  53.     local oldfile="$2"
  54.     local newfile="$3"
  55.    
  56.     if [[ -z "$header" ]]; then
  57.         printf '#Automatically generated by %s at %s\n' "$self" "$(date +'%F %T')"
  58.         printf '#arguments:'
  59.         printf ' %q' "${args[@]}"
  60.         printf '\ncd %q\n' "$PWD"
  61.     fi
  62.    
  63.     printf "mv -- %q %q\n" "$oldfile" "$newfile"
  64. }
  65.  
  66. addfiles() {
  67.     local arg="$1"
  68.     [[ -f "$arg" ]] && { files+=( "$arg"       ) ; return ; } # add file
  69.     [[ -d "$arg" ]] && { files+=( "${arg%/}/"* ) ; return ; } # add files in dir
  70.     fatal "\'$arg\' is not a file or directory"
  71. }
  72.  
  73. #save for log
  74. args=( "$@" )
  75.  
  76. # command line parsing
  77. while [[ $# -gt 0 ]]; do
  78.     arg="$1"; shift
  79.     case "$arg" in
  80.     -h|--help   ) usage           ;;
  81.     -t|--run    ) run=1           ;;
  82.     -v|--verbose) verbose=1       ;;
  83.     -u|--undo   ) undo="$1";shift ;;
  84.     --          ) break           ;;
  85.     *           ) addfiles "$arg" ;;
  86.     esac
  87. done
  88. for arg; do addfiles "$arg"; done # add remaining files after --
  89. [[ "${#files[@]}" -gt 0 ]] || addfiles "$PWD" # no files given: add current dir
  90.  
  91. # loop the files
  92. prevdir=""
  93. match=""
  94. for video in "${files[@]}"; do
  95.  
  96.     # File exists? (can be an umatched glob or empty dir)
  97.     [[ -f "$video" ]] || continue
  98.  
  99.     # Split full filename in file, title, ext and dir (with trailing '/')
  100.     file="${video##*/}"
  101.     title="${file%.*}"
  102.     ext="${file#"$title"}"
  103.     ext="${ext#.}"
  104.     dir="${video%"$file"}"
  105.     dir="${dir:-./}"
  106.  
  107.     # Is it a video?
  108.     case "${ext,,}" in avi|mpg|mpeg|mkv|mp4) ;; *) continue ;; esac
  109.  
  110.     # Has a matching subtitle already?
  111.     subtitle="${video%."$ext"}.srt"
  112.     [[ -f "$subtitle" ]] && continue
  113.  
  114.     # Populate the unmatched subtitles array for this dir
  115.     if [[ "$dir" != "$prevdir" ]]; then
  116.         prevdir="$dir"
  117.         allsubs=( "${dir%/}"/*.[Ss][Rr][Tt] )
  118.         subtitles=()
  119.         s=0
  120.         for sub in "${allsubs[@]}"; do
  121.             if [[ -f "$sub" ]]; then
  122.                 matchsub=""
  123.                 for f in "${sub%.[Ss][Rr][Tt]}".{avi,mpg,mpeg,mkv,mp4}; do
  124.                     if [[ -f "$f" ]]; then matchsub=1; break; fi
  125.                 done
  126.                 [[ "$matchsub" ]] || subtitles+=( "$sub" )
  127.             fi
  128.         done
  129.     fi
  130.    
  131.     # Are there any avaliable, unmatched subtitles left in this dir?
  132.     (( s < ${#subtitles[@]} )) || continue
  133.    
  134.     # Rename the first subtitle
  135.     [[ "$verbose" ]] && printf 'old=%s\tnew=%s\n' "${subtitles[s]}" "${subtitle}"
  136.     [[ "$undo" ]] && printundo "$match" "${subtitle}" "${subtitles[s]}" >> "$undo" || fatal "could not write to undo file $undo"
  137.     [[ "$run" ]] && { mv -- "${subtitles[s]}" "${subtitle}" || fatal "could not rename ${subtitles[s]}" ; }
  138.     match=1
  139.     (( s++ ))
  140.    
  141. done
  142.  
  143. if [[ "$undo" && "$match" ]]; then
  144.     printf '\n' >> "$undo" || fatal "could not write to undo file $undo"
  145.     chmod +x "$undo" || fatal "could not set to executable undo script $undo"
  146. fi
  147.  
  148. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement