/* Episode Renamer v1.5b2 by FND reads a list of episode titles from file, then allows renaming the selected file(s) accordingly using the F12 key */ /* ToDo: - use proper GUIs -> add main menu -> comparison list (use ListBox) => option to re-arrange list -> episode codes */ /* change history ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ # v1.0 (2006-02-26) * first (and probably final) release # v1.1 (2006-03-15) * added a proper tray menu * added a short descriptions and help message # v1.2 (2006-04-15) * fixed a bug where the counter was not reset after re-selecting the source file # v1.5b2 (2006-05-17) * changed the renaming process from having to press a hotkey for each indi- vidual file in Windows Explorer to automatically processing all selected files (the previous method was prone to errors) * added option to automatically add episode codes * added option to manually enter episode titles */ /* ********** settings, variable declarations ********** */ #SingleInstance Force OnExit, quit programName = Episode Renamer programVersion = 1.5b2 programFullName = %programName% v%programVersion% programAuthor = FND /* ********** auto-execute section ********** */ ; construct tray menu GoSub, trayMenu ; get list of files to be renamed GoSub, getTargetFiles ; get list of episode titles GoSub, getTitles ; show comparison list of target files and their respective titles GoSub, showFileTitles ; terminate script GoSub, quit ; end of auto-execute section Return /* ********** hotkeys ********** */ ; [ALT]+[ESC]: terminate script !Esc:: GoSub, quit Return /* ********** subroutines ********** */ trayMenu: Menu, Tray, Tip, %programFullName% Menu, Tray, NoStandard Menu, Tray, Add, About, about Menu, Tray, Add, Help, help Menu, Tray, Add ; separator Menu, Tray, Add, Exit, quit Return ; get list of files to be renamed getTargetFiles: targetPath := A_WorkingDir targetFiles = Loop { fileBlock = FileSelectFile, fileBlock, M3, %targetPath% , %programFullName% - Please select the files to be renamed (block #%A_Index%). ; DEBUG: A_Index incorrect if no files were selected in the first place (see below) If fileBlock != { ; append list of target files targetFiles = %targetFiles%%fileBlock%`n ; retain previous path for file selection dialog - DEBUG: correct?? StringSplit, targetPaths, fileBlock, `n targetPath := targetPaths1 } Else { If targetFiles = ; no files have been selected yet MsgBox, 0, %programFullName% , No target files selected - please select at least one file. Else ; file-selection complete Break } } fileCount = 0 Loop, Parse, targetFiles, `n { If IsFolder(A_LoopField) targetPath := A_LoopField ; DEBUG: no support for selections from multiple folders!? Else If A_LoopField != { fileCount++ targetFile%fileCount% := A_LoopField } } ; add trailing backslash to target path StringRight, dummy, targetPath, 1 If (dummy != "\") targetPath = %targetPath%\ Return ; get list of episode titles getTitles: titleCount = 0 FileSelectFile, sourceFile, 3, %targetPath% , %programFullName% - Please select the source for the episode titles. , plain-text files (*.txt) If sourceFile = { MsgBox, 4, %programFullName% , No source file selected. Do you want to enter the titles manually? IfMsgBox, Yes { Loop { InputBox, title%A_Index%, %programFullName% , Please enter title #%A_Index%. If title%A_Index% != titleCount++ Else break } } } IfMsgBox, No GoSub, quit Loop, Read, %sourceFile% { If A_LoopReadLine != ; skip blank lines { titleCount++ title%titleCount% := A_LoopReadLine } } ; re-initialize counter i = 1 ; automatically add episode codes MsgBox, 4, %programFullName% , Automatically add episode codes (e.g. "01x01")? IfMsgBox, Yes GoSub, addEpisodeCodes Return ; automatically add episode codes addEpisodeCodes: ; define code format: [prefix]##[separator]##[suffix] - DEBUG: use proper GUI!? InputBox, prefix, %programFullName% , Please enter desired prefix. InputBox, separator, %programFullName% , Please enter desired separator between season and episode number. InputBox, suffix, %programFullName% , Please enter desired suffix. InputBox, firstSeason, %programFullName% , Please enter the number of the first season. InputBox, firstEpisode, %programFullName% , Please enter the number of the first episode. InputBox, lastSeason, %programFullName% , Please enter the number of the last season. InputBox, lastEpisode, %programFullName% , Please enter the number of the last episode. InputBox, episodesPerSeason, %programFullName% , Please enter the number of episodes per season. ; DEBUG: no support for varying season lengths?! MsgBox, 4, %programFullName% , The final format will look like this:`n`n%prefix%##%separator%##%suffix%[title]`n`nIs this correct? IfMsgBox, No ; repeat process GoSub, addEpisodeCodes IfMsgBox, Yes ; add codes { currentEpisode := firstEpisode currentSeason := firstSeason Loop { If title%A_Index% != { ; add leading zeros If currentEpisode > 9 episodeString := currentEpisode Else episodeString = 0%currentEpisode% If currentSeason > 9 seasonString := currentSeason Else seasonString = 0%currentSeason% ; compose new title episodeCode := prefix . seasonString . separator . episodeString . suffix title%A_Index% := episodeCode title%A_Index% ; increase counter If currentSeason < %lastSeason% { If currentEpisode < %episodesPerSeason% currentEpisode++ Else ; jump to next season { currentEpisode = 1 currentSeason++ } } Else If currentEpisode < %lastEpisode% currentEpisode++ Else ; last episode of last season reached break } Else break } } Return ; show comparison list of target files and their respective titles showFileTitles: ; notfiy user if there are more target files than titles or vice versa If fileCount > %titleCount% MsgBox, 0, %programFullName% , % "There are " . fileCount - titleCount . " more files than titles.`nThe last " . fileCount - titleCount . " files will be ignored." Else If titleCount > %fileCount% MsgBox, 0, %programFullName% , % "There are " . titleCount - fileCount . " more titles than files.`nThe last " . titleCount - fileCount . " titles will be ignored." ; create comparison list fileTitles = Loop { If (title%A_Index% = "" OR targetFile%A_Index% = "") break Else { fileTitles := fileTitles title%A_Index% A_Tab "||" A_Tab targetFile%A_Index% "`n" } } ; show comparison list and request approval MsgBox, 4, %programFullName% , Title%A_Tab%||%A_Tab%File`n`n%fileTitles%`nIs this correct? ; DEBUG: use proper GUI (ListBox) instead? => option to re-arrange list IfMsgBox, No { MsgBox, 0, %programFullName%, Aborted by user. GoSub, quit } IfMsgBox, Yes GoSub, renameFiles Return ; rename target files renameFiles: If fileCount <= %titleCount% counter := fileCount Else If titleCount < %fileCount% counter := titleCount renameErrors = Loop, %counter% { currentFile := targetPath targetFile%A_Index% currentTitle := targetPath title%A_Index% ; retrieve file extension StringGetPos, separatorPos, currentFile, ., R fileExtension_chars := StrLen(currentFile) - separatorPos StringRight, currentFileExtension, currentFile, %fileExtension_chars% ; rename file - DEBUG: missing error handling for special chars (e.g. "Déjà Vu") If (FileExist(currentTitle . currentFileExtension) OR ErrorLevel != 0) renameErrors = ( LTrim Join %renameErrors%%currentFile% to`n %currentTitle%%currentFileExtension%`n`n ) Else FileMove, %currentFile%, %currentTitle%%currentFileExtension% } If renameErrors = MsgBox, 0, %programFullName% , Renaming successful. Else MsgBox, 0, %programFullName% , The following error(s) occured during renaming:`n`n%renameErrors% Return ; show info message about: MsgBox, 64, %programFullName%, ( LTrim Join %programFullName%`n %A_Space%by %programAuthor%`n `n A little tool to easily rename video files (and TV episodes in parti cular).`n ) Return ; show help message - DEBU: revise (also include note that selection order of target files does matter) help: MsgBox, 64, %programFullName%, ( LTrim Join How to use:`n `n 1. Create a plain-text file with the episode names (one title per li ne).`n 2. Start this program and select the text file.`n 3. Select the first episode in Explorer and press F12 - this will re name the file and automatically select the next one.`n 4. Repeat step #3 as many times as required. ) Return ; terminate script quit: ExitApp Return ; check whether path is a folder IsFolder(path) { FileGetAttrib, att, %path% IfInString, att, D Return True Else Return False }