Luis Diaz
asked on
AutoHotkey: Rename files
Hello Experts,
The following AutoHotkey function allows to select files attributes / components.
I want to take as a reference to cover the following sequence:
1.I select a file or multiple files
2.I launch the AutoHotkey script
3.Files should be rename by talking to account the following:
- Special characters such as ‘(‘, ‘)’, '\', '/', '. ', '?' , and '* should be replaced by -
-Just the first letter should be upper
-If the last character prior to extension is a special character it should be removed
-Example: TesT file name (9).pdf
-After I execute the script I expect to have the following name: Test-file-name-9.pdf
If you have questions, please contact me.
Thank you for your help.
The following AutoHotkey function allows to select files attributes / components.
GetSelectedFile(hwnd:="",FileComponents:=1,GetDate:=1) {
; this function by sinkfaze: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=77#p395
WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A")
WinGetClass class, ahk_id %hwnd%
if (process = "explorer.exe")
if (class ~= "Progman|WorkerW") {
ControlGet, files, List, Selected Col1, SysListView321, ahk_class %class%
Loop, Parse, files, `n, `r
ToReturn .= A_Desktop "\" A_LoopField "`n"
}
else if (class ~= "(Cabinet|Explore)WClass") {
for window in ComObjCreate("Shell.Application").Windows
if (window.hwnd==hwnd)
sel := window.Document.SelectedItems
for item in sel
{
FileFullPath:=item.path
If (FileComponents=1)
FileParts:=FileFullPath
If (FileComponents=2)
SplitPath,FileFullPath,,,,FileParts
If (FileComponents=3)
SplitPath,FileFullPath,FileParts
If (GetDate>1)
{
ToReturn .= DateParse(item.ModifyDate) . A_Tab . FileParts . "`n"
If (GetDate=2)
Sort,ToReturn ; GetDate=2 --> modified date sorted ascending
Else
Sort,ToReturn,R ; GetDate=3 --> modified date sorted descending
}
else
ToReturn .= FileParts "`n" ; GetDate=1 --> no date/sort
}
}
return Trim(ToReturn,"`n")
}
I want to take as a reference to cover the following sequence:
1.I select a file or multiple files
2.I launch the AutoHotkey script
3.Files should be rename by talking to account the following:
- Special characters such as ‘(‘, ‘)’, '\', '/', '. ', '?' , and '* should be replaced by -
-Just the first letter should be upper
-If the last character prior to extension is a special character it should be removed
-Example: TesT file name (9).pdf
-After I execute the script I expect to have the following name: Test-file-name-9.pdf
If you have questions, please contact me.
Thank you for your help.
ASKER
Hi Joe,
Sorry for the mistakes. Here is the revised spec:
-The following characters should be replaced by '-' : !#$%&'()+,.;=@[]^_`{}~ and espace
-In order to avoid complexity I drop . (period) replacement.
Let me know if it is clearer.
Regards,
Luis.
Sorry for the mistakes. Here is the revised spec:
-The following characters should be replaced by '-' : !#$%&'()+,.;=@[]^_`{}~ and espace
-In order to avoid complexity I drop . (period) replacement.
Let me know if it is clearer.
Regards,
Luis.
> In order to avoid complexity I drop . (period) replacement.
First, the dot is still in your list (between the comma and the semi-colon). Second, it's not complex to replace all dots except for the one prior to the extension...would you like to do that? Also, what do you want to do if the file rename results in a file that already exists?
First, the dot is still in your list (between the comma and the semi-colon). Second, it's not complex to replace all dots except for the one prior to the extension...would you like to do that? Also, what do you want to do if the file rename results in a file that already exists?
ASKER
Ok. In that case we include dot in the replacement. I file name already exists two options:
-Block the process with msgbox displayed
-Nice to have: add date stamp (yyyymmddhhmmss-) string in order to differentiate with the one that already exists.
I prefer the second.
-Block the process with msgbox displayed
-Nice to have: add date stamp (yyyymmddhhmmss-) string in order to differentiate with the one that already exists.
I prefer the second.
To be clear, you don't want anything in the path or extension to be changed...right? In other words, only the file name portion will have characters changed...not the file path and not the file extension...right?
For example, consider this:
c:\My Tax Files (Federal)\TesT file name (9).tax[2019]
Only this component of the full file path/name will be subject to the rename:
TesT file name (9)
Right?
For example, consider this:
c:\My Tax Files (Federal)\TesT file name (9).tax[2019]
Only this component of the full file path/name will be subject to the rename:
TesT file name (9)
Right?
ASKER
Right, only the file name portion will have characters changed.
OK. I'm busy right now but will try to post some code for you later today. Regards, Joe
ASKER
Don't worry Joe, I can wait. Thank you for your comment! have a great weekend!
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi Joe,
Thank you very much for this proposal.
Prior the testing I was trying to add to my AutoHotkey file.
I got the following error:
LD-autohotkey.ahk (1382) : ==> Duplicate label
Which refers to: ButtonOK
I check which are the other AutoHotkey script that use this label and I found:
Do you know how can I manage this? Knowing that the final objective is to add this script to my AutoHotkey in which are all the AutoHotkey scripts.
Thank you in advance for your feedback.
Regards,
Luis.
Thank you very much for this proposal.
Prior the testing I was trying to add to my AutoHotkey file.
I got the following error:
LD-autohotkey.ahk (1382) : ==> Duplicate label
Which refers to: ButtonOK
I check which are the other AutoHotkey script that use this label and I found:
;====================================
;Copy file name, file path
;====================================
+F1::
Gui,Add,Radio,Checked vComponents xm,FileFullPath
Gui,Add,Radio,x+20,FileNoPathNoExt
Gui,Add,Radio,x+20,FileNoPathWithExt
Gui,Add,Text
Gui,Add,Radio,Checked vDate xm,No Date
Gui,Add,Radio,x+20,Date
Gui,Add,Text
Gui,Add,Button,xm Default,&OK
Gui,Add,Button,x+20,&Cancel
Gui,Show,,Copy to Clipboard
Return
ButtonOK:
Gui,Submit
Gui,Destroy
If (!WinActive("ahk_class CabinetWClass"))
{
MsgBox,4144,Error,Active window is not Windows/File Explorer
Return
}
AllFileComponents:=""
SelectedFiles:=GetSelectedFile("",Components,Date)
If (SelectedFiles="")
{
MsgBox,4144,Error,No files are selected in Windows/File Explorer
Return
}
Clipboard:=SelectedFiles
ClipWait,2 ; wait for information to appear on clipboard
If (ErrorLevel=1)
MsgBox,4144,Error,Information did not appear on clipboard after two seconds
Return
ButtonCancel:
GuiClose:
GuiEscape:
Gui,Destroy
Return
Do you know how can I manage this? Knowing that the final objective is to add this script to my AutoHotkey in which are all the AutoHotkey scripts.
Thank you in advance for your feedback.
Regards,
Luis.
Hi Luis,
That's a common issue. To solve it, use a g-label, documented here:
https://www.autohotkey.com/docs/commands/Gui.htm#label
The idea is not to use the button name as the implicit Gosub label, but instead use an explicit Gosub label that is different for the buttons in multiple GUIs within the same script (obviously, this would apply to other buttons, too, such as Cancel, Retry, Submit, etc.).
In this case, which calls the new RenameSelectedFile, change:
Gui,Add,Button,xm Default,&OK
Gui,Add,Button,x+20,&Cance l
To:
Gui,Add,Button,xm gButtonRenameOK Default,&OK
Gui,Add,Button,x+20 gButtonRenameCancel,&Cance l
Then change:
ButtonOK:
ButtonCancel:
To:
ButtonRenameOK:
ButtonRenameCancel:
I would also do the same for the other GUI so that you are well-positioned for future additions, that is, in the GUI that calls GetSelectedFile, change:
Gui,Add,Button,xm Default,&OK
Gui,Add,Button,x+20,&Cance l
To:
Gui,Add,Button,xm gButtonGetOK Default,&OK
Gui,Add,Button,x+20 gButtonGetCancel,&Cancel
Then change:
ButtonOK:
ButtonCancel:
To:
ButtonGetOK:
ButtonGetCancel:
That should do it! As you continue to add GUIs with OK and Cancel (and other) buttons, use this technique to assure that the g-labels are unique. Regards, Joe
That's a common issue. To solve it, use a g-label, documented here:
https://www.autohotkey.com/docs/commands/Gui.htm#label
The idea is not to use the button name as the implicit Gosub label, but instead use an explicit Gosub label that is different for the buttons in multiple GUIs within the same script (obviously, this would apply to other buttons, too, such as Cancel, Retry, Submit, etc.).
In this case, which calls the new RenameSelectedFile, change:
Gui,Add,Button,xm Default,&OK
Gui,Add,Button,x+20,&Cance
To:
Gui,Add,Button,xm gButtonRenameOK Default,&OK
Gui,Add,Button,x+20 gButtonRenameCancel,&Cance
Then change:
ButtonOK:
ButtonCancel:
To:
ButtonRenameOK:
ButtonRenameCancel:
I would also do the same for the other GUI so that you are well-positioned for future additions, that is, in the GUI that calls GetSelectedFile, change:
Gui,Add,Button,xm Default,&OK
Gui,Add,Button,x+20,&Cance
To:
Gui,Add,Button,xm gButtonGetOK Default,&OK
Gui,Add,Button,x+20 gButtonGetCancel,&Cancel
Then change:
ButtonOK:
ButtonCancel:
To:
ButtonGetOK:
ButtonGetCancel:
That should do it! As you continue to add GUIs with OK and Cancel (and other) buttons, use this technique to assure that the g-labels are unique. Regards, Joe
ASKER
Notes Joe, thank you very much for this advice. I will test it and keep you informed.
ASKER
Hi Joe,
I modified as recommended but I am having problems with duplicate label related to GuiClose which appears in both scripts.
I supposed that I am going to have the same problem with GuiEscape and Gui,Destroy. I don't know how to proceed as those are not declared at the beginning of the AutoHotkey scripts. Could you please let me know what is the best approach for this?
Thank you for your help.
I modified as recommended but I am having problems with duplicate label related to GuiClose which appears in both scripts.
;====================================
;Rename files and replace special characters
;====================================
^+F12:: ; Ctrl+Shift+F12 - as always, make hotkey whatever you want
Gui,Add,Radio,Checked vComponents xm,FileFullPath
Gui,Add,Radio,x+20,FileNoPathNoExt
Gui,Add,Radio,x+20,FileNoPathWithExt
Gui,Add,Text
Gui,Add,Radio,Checked vDate xm,No Date
Gui,Add,Radio,x+20,Date
Gui,Add,Text
Gui,Add,Button,xm gButtonRenameOK Default,&OK
Gui,Add,Button,x+20 gButtonRenameCancel,&Cancel
Gui,Show,,Copy to Clipboard
Return
gButtonRenameOK:
Gui,Submit
Gui,Destroy
If (!WinActive("ahk_class CabinetWClass"))
{
MsgBox,4144,Error,Active window is not Windows/File Explorer
Return
}
AllFileComponents:=""
SelectedFiles:=RenameSelectedFile("",Components,Date)
If (SelectedFiles="")
{
MsgBox,4144,Error,No files are selected in Windows/File Explorer
Return
}
Clipboard:=SelectedFiles
ClipWait,2 ; wait for information to appear on clipboard
If (ErrorLevel=1)
MsgBox,4144,Error,Information did not appear on clipboard after two seconds
Return
gButtonRenameCancel:
GuiClose:
GuiEscape:
Gui,Destroy
Return
;====================================
;Copy file name, file path
;====================================
+F1::
Gui,Add,Radio,Checked vComponents xm,FileFullPath
Gui,Add,Radio,x+20,FileNoPathNoExt
Gui,Add,Radio,x+20,FileNoPathWithExt
Gui,Add,Text
Gui,Add,Radio,Checked vDate xm,No Date
Gui,Add,Radio,x+20,Date
Gui,Add,Text
Gui,Add,Button,xm gButtonGetOK Default,&OK
Gui,Add,Button,x+20 gButtonGetCancel,&Cancel
Gui,Show,,Copy to Clipboard
Return
gButtonGetOK:
Gui,Submit
Gui,Destroy
If (!WinActive("ahk_class CabinetWClass"))
{
MsgBox,4144,Error,Active window is not Windows/File Explorer
Return
}
AllFileComponents:=""
SelectedFiles:=GetSelectedFile("",Components,Date)
If (SelectedFiles="")
{
MsgBox,4144,Error,No files are selected in Windows/File Explorer
Return
}
Clipboard:=SelectedFiles
ClipWait,2 ; wait for information to appear on clipboard
If (ErrorLevel=1)
MsgBox,4144,Error,Information did not appear on clipboard after two seconds
Return
gButtonGetCancel:
GuiClose:
GuiEscape:
Gui,Destroy
Return
I supposed that I am going to have the same problem with GuiEscape and Gui,Destroy. I don't know how to proceed as those are not declared at the beginning of the AutoHotkey scripts. Could you please let me know what is the best approach for this?
Thank you for your help.
Delete the second GuiClose and GuiEscape labels (lines 84 and 85 in your posted code). The second Gui,Destroy is not a problem because it's not a label.
Also, the g on the actual labels is wrong. You want them in the Gui,Add,Button lines, but not in the labels themselves. In other words, change lines 18, 39, 62, 83 in your posted code as follows:
ButtonRenameOK:
ButtonRenameCancel:
ButtonGetOK:
ButtonGetCancel:
Regards, Joe
Also, the g on the actual labels is wrong. You want them in the Gui,Add,Button lines, but not in the labels themselves. In other words, change lines 18, 39, 62, 83 in your posted code as follows:
ButtonRenameOK:
ButtonRenameCancel:
ButtonGetOK:
ButtonGetCancel:
Regards, Joe
ASKER
Joe, I tested as proposed and now it works!
I was wondering why the various options: FileFullPath/FileNoPathNoE xt/FileNoP athWithExt reported at GUI are available for selection. If the main objective is to rename file why not simplify and avoid having the GUI for selection as there is not value added in that specific case. Why not having the msgbox box approach.
I tried the following:
However I am having some issues:
I got the following message even if file is renamed: MsgBox,4144,Error,No files are selected in Windows/File Explorer
and the revised name is not sent to the clipboard.
If you can help me to fix this it would be great!
Thank you for your help.
Regards,
Luis.
I was wondering why the various options: FileFullPath/FileNoPathNoE
I tried the following:
^+F12:: ; Ctrl+Shift+F12 - as always, make hotkey whatever you want
If (!WinActive("ahk_class CabinetWClass"))
{
MsgBox,4144,Error,Active window is not Windows/File Explorer
Return
}
MsgBox,4131,Do you want to rename selected files, The following chars `%`!`#`$`%`&`'`(`)`+`,`.`;`=`@`[`]`^`_```{`}`~ and space are going to be replace: ?,Press YES to rename selected files`n`nPress CANCEL to exit/quit (not do do the rename)
IfMsgBox,Cancel
Return
IfMsgBox,Yes
AllFileComponents:=""
SelectedFiles:=RenameSelectedFile("",Components,Date)
If (SelectedFiles="")
{
MsgBox,4144,Error,No files are selected in Windows/File Explorer
Return
}
Clipboard:=SelectedFiles
ClipWait,2 ; wait for information to appear on clipboard
If (ErrorLevel=1)
{
MsgBox,4144,Error, No text appearing after one second
Return
}
;====================================
;Function use to rename selected files
;====================================
RenameSelectedFile(hwnd:="",FileComponents:=1,GetDate:=1) {
; much of this function by sinkfaze: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=77#p395
; some of it by Joe Winograd for this EE question
WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A")
WinGetClass class, ahk_id %hwnd%
if (process = "explorer.exe")
if (class ~= "Progman|WorkerW") {
ControlGet, files, List, Selected Col1, SysListView321, ahk_class %class%
Loop, Parse, files, `n, `r
ToReturn .= A_Desktop "\" A_LoopField "`n"
}
else if (class ~= "(Cabinet|Explore)WClass") {
for window in ComObjCreate("Shell.Application").Windows
if (window.hwnd==hwnd)
sel := window.Document.SelectedItems
for item in sel
{
FileFullPath:=item.path
SplitPath,FileFullPath,FileNameWithExt,FilePath,FileExt,FileNameNoExt,FileDrive
FileNameNoExt:=RegExReplace(FileNameNoExt,"[\x20\x60\!\#\$\%\&\'\(\)\+\,\.\;\=\@\[\]\^\_\{\}\~]","-") ; replace special chars with hyphen, but only in FileNameNoExt
StringLower,FileNameNoExt,FileNameNoExt,T ; make all letters lower case except for first letter (this works because there are no spaces...hyphens replaced them)
FileFullPathNew:=FilePath . "\" . FileNameNoExt . "." . FileExt
If (FileExist(FileFullPathNew))
{
FileNameNoExt:=FileNameNoExt . "-" . A_Now ; if files exists, add YYYYMMDDhhmmss to file name (preceded by a hyphen)
FileFullPathNew:=FilePath . "\" . FileNameNoExt . "." . FileExt
}
FileMove,%FileFullPath%,%FileFullPathNew%
If (ErrorLevel!=0)
MsgBox,4144,Rename Error,Error Level=%ErrorLevel% trying to rename:`n%FileFullPath%`nTo:`n%FileFullPathNew%
If (FileComponents=1)
FileParts:=FileFullPathNew
If (FileComponents=2)
FileParts:=FileNameNoExt
If (FileComponents=3)
FileParts:=FileNameNoExt . "." . FileExt
If (GetDate>1)
{
ToReturn .= DateParse(item.ModifyDate) . A_Tab . FileParts . "`n"
If (GetDate=2)
Sort,ToReturn ; GetDate=2 --> modified date sorted ascending
Else
Sort,ToReturn,R ; GetDate=3 --> modified date sorted descending
}
else
ToReturn .= FileParts "`n" ; GetDate=1 --> no date/sort
}
}
return Trim(ToReturn,"`n")
}
;====================================
;Function to get date format used for sort by date and related to GetSelectFile function
;====================================
DateParse(str) {
; this function by polyethene: https://autohotkey.com/board/topic/18760-date-parser-convert-any-date-format-to-yyyymmddhh24miss/
static e2 = "i)(?:(\d{1,2}+)[\s\.\-\/,]+)?(\d{1,2}|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\w*)[\s\.\-\/,]+(\d{2,4})"
str := RegExReplace(str, "((?:" . SubStr(e2, 42, 47) . ")\w*)(\s*)(\d{1,2})\b", "$3$2$1", "", 1)
If RegExMatch(str, "i)^\s*(?:(\d{4})([\s\-:\/])(\d{1,2})\2(\d{1,2}))?"
. "(?:\s*[T\s](\d{1,2})([\s\-:\/])(\d{1,2})(?:\6(\d{1,2})\s*(?:(Z)|(\+|\-)?"
. "(\d{1,2})\6(\d{1,2})(?:\6(\d{1,2}))?)?)?)?\s*$", i)
d3 := i1, d2 := i3, d1 := i4, t1 := i5, t2 := i7, t3 := i8
Else If !RegExMatch(str, "^\W*(\d{1,2}+)(\d{2})\W*$", t)
RegExMatch(str, "i)(\d{1,2})\s*:\s*(\d{1,2})(?:\s*(\d{1,2}))?(?:\s*([ap]m))?", t)
, RegExMatch(str, e2, d)
f = %A_FormatFloat%
SetFormat, Float, 02.0
d := (d3 ? (StrLen(d3) = 2 ? 20 : "") . d3 : A_YYYY)
. ((d2 := d2 + 0 ? d2 : (InStr(e2, SubStr(d2, 1, 3)) - 40) // 4 + 1.0) > 0
? d2 + 0.0 : A_MM) . ((d1 += 0.0) ? d1 : A_DD) . t1
+ (t1 = 12 ? t4 = "am" ? -12.0 : 0.0 : t4 = "am" ? 0.0 : 12.0) . t2 + 0.0 . t3 + 0.0
SetFormat, Float, %f%
Return, d
}
However I am having some issues:
I got the following message even if file is renamed: MsgBox,4144,Error,No files are selected in Windows/File Explorer
and the revised name is not sent to the clipboard.
If you can help me to fix this it would be great!
Thank you for your help.
Regards,
Luis.
> I tested as proposed and now it works!
Glad to hear it.
> If the main objective is to rename file why not simplify and avoid having the GUI for selection as there is not value added in that specific case.
This is entirely up to what the user wants...you! It's your program, not mine. The specifications/requirement s of the program are yours...make it do whatever you want.
> Why not having the msgbox box approach.
If that's what you want...fine.
> I tried the following
There are numerous problems in your code:
(1) After your IfMsgBox,Yes command (line 10), there should be a code block. As it stands now, only the one statement (line 11) would be in the True path of the IfMsgBox,Yes. If that were what you really want (it isn't), proper coding practice would indent it, just as line 9 (Return) is indented, because it's the only statement in the True path of line 8 (IfMsgBox,Cancel).
(2) There seems to be no need for three choices in the line 7 MsgBox. Seems to me that two would be fine...either Yes/No (4132) or OK/Cancel (4129), depending on how you phrase the question for the user. I suggest replacing lines 7-10 with these:
https://www.autohotkey.com/docs/Functions.htm
What you want there is this:
Glad to hear it.
> If the main objective is to rename file why not simplify and avoid having the GUI for selection as there is not value added in that specific case.
This is entirely up to what the user wants...you! It's your program, not mine. The specifications/requirement
> Why not having the msgbox box approach.
If that's what you want...fine.
> I tried the following
There are numerous problems in your code:
(1) After your IfMsgBox,Yes command (line 10), there should be a code block. As it stands now, only the one statement (line 11) would be in the True path of the IfMsgBox,Yes. If that were what you really want (it isn't), proper coding practice would indent it, just as line 9 (Return) is indented, because it's the only statement in the True path of line 8 (IfMsgBox,Cancel).
(2) There seems to be no need for three choices in the line 7 MsgBox. Seems to me that two would be fine...either Yes/No (4132) or OK/Cancel (4129), depending on how you phrase the question for the user. I suggest replacing lines 7-10 with these:
MsgBox,4132,Do you want to rename selected files?,A hyphen will replace these character:`n`n`%`!`#`$`%`&`'`(`)`+`,`.`;`=`@`[`]`^`_```{`}`~ and space`n`nPress Yes to rename or No to quit and not rename
IfMsgBox,No
Return
(3) Your RenameSelectedFile call (line 12) is bad. You are calling it with parameters Components and Date, but neither of those has been assigned a value. If you don't understand how functions are called and what the parameters mean, you should study the doc here:https://www.autohotkey.com/docs/Functions.htm
What you want there is this:
SelectedFiles:=RenameSelectedFile()
(4) You have no code in the False path of the If (ErrorLevel=1) statement (line 20)...it falls through to whatever code is under it. You should have a Return there. Another method is to change lines 20-24 to these:If (ErrorLevel=1)
MsgBox,4144,Error, No text appearing after one second
Return
Regards, Joe
ASKER
Thank you very much for this comment Joe!
I reviewed as recommended like this: (I hope I didn't make a lot of mistakes):
I tested with multiple characters and files selected and it works.
Concerning: your comment:
I am trying to understand why in your proposal:
#a43022090 you call the function with Components and Date. I supposed that it is because the buttons related to the GUI which use date and the various files components which is not the case for the msgbox approach.
Regards,
Luis.
I reviewed as recommended like this: (I hope I didn't make a lot of mistakes):
I tested with multiple characters and files selected and it works.
^+F12:: ; Ctrl+Shift+F12 - as always, make hotkey whatever you want
If (!WinActive("ahk_class CabinetWClass"))
{
MsgBox,4144,Error,Active window is not Windows/File Explorer
Return
}
MsgBox,4132,Do you want to rename selected files?,A hyphen will replace these character:`n`n`%`!`#`$`%`&`'`(`)`+`,`.`;`=`@`[`]`^`_```{`}`~ and space`n`nPress Yes to rename or No to quit and not rename
IfMsgBox,No
Return
IfMsgBox,Yes
{
AllFileComponents:=""
SelectedFiles:=RenameSelectedFile()
If (SelectedFiles="")
{
MsgBox,4144,Error,No files are selected in Windows/File Explorer
Return
}
Clipboard:=SelectedFiles
ClipWait,2 ; wait for information to appear on clipboard
If (ErrorLevel=1)
MsgBox,4144,Error, No text appearing after one second
Return
}
;====================================
;Function use to rename selected files
;====================================
RenameSelectedFile(hwnd:="",FileComponents:=1,GetDate:=1) {
; much of this function by sinkfaze: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=77#p395
; some of it by Joe Winograd for this EE question
WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A")
WinGetClass class, ahk_id %hwnd%
if (process = "explorer.exe")
if (class ~= "Progman|WorkerW") {
ControlGet, files, List, Selected Col1, SysListView321, ahk_class %class%
Loop, Parse, files, `n, `r
ToReturn .= A_Desktop "\" A_LoopField "`n"
}
else if (class ~= "(Cabinet|Explore)WClass") {
for window in ComObjCreate("Shell.Application").Windows
if (window.hwnd==hwnd)
sel := window.Document.SelectedItems
for item in sel
{
FileFullPath:=item.path
SplitPath,FileFullPath,FileNameWithExt,FilePath,FileExt,FileNameNoExt,FileDrive
FileNameNoExt:=RegExReplace(FileNameNoExt,"[\x20\x60\!\#\$\%\&\'\(\)\+\,\.\;\=\@\[\]\^\_\{\}\~]","-") ; replace special chars with hyphen, but only in FileNameNoExt
StringLower,FileNameNoExt,FileNameNoExt,T ; make all letters lower case except for first letter (this works because there are no spaces...hyphens replaced them)
FileFullPathNew:=FilePath . "\" . FileNameNoExt . "." . FileExt
If (FileExist(FileFullPathNew))
{
FileNameNoExt:=FileNameNoExt . "-" . A_Now ; if files exists, add YYYYMMDDhhmmss to file name (preceded by a hyphen)
FileFullPathNew:=FilePath . "\" . FileNameNoExt . "." . FileExt
}
FileMove,%FileFullPath%,%FileFullPathNew%
If (ErrorLevel!=0)
MsgBox,4144,Rename Error,Error Level=%ErrorLevel% trying to rename:`n%FileFullPath%`nTo:`n%FileFullPathNew%
If (FileComponents=1)
FileParts:=FileFullPathNew
If (FileComponents=2)
FileParts:=FileNameNoExt
If (FileComponents=3)
FileParts:=FileNameNoExt . "." . FileExt
If (GetDate>1)
{
ToReturn .= DateParse(item.ModifyDate) . A_Tab . FileParts . "`n"
If (GetDate=2)
Sort,ToReturn ; GetDate=2 --> modified date sorted ascending
Else
Sort,ToReturn,R ; GetDate=3 --> modified date sorted descending
}
else
ToReturn .= FileParts "`n" ; GetDate=1 --> no date/sort
}
}
return Trim(ToReturn,"`n")
}
;====================================
;Function to get date format used for sort by date and related to GetSelectFile function
;====================================
DateParse(str) {
; this function by polyethene: https://autohotkey.com/board/topic/18760-date-parser-convert-any-date-format-to-yyyymmddhh24miss/
static e2 = "i)(?:(\d{1,2}+)[\s\.\-\/,]+)?(\d{1,2}|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\w*)[\s\.\-\/,]+(\d{2,4})"
str := RegExReplace(str, "((?:" . SubStr(e2, 42, 47) . ")\w*)(\s*)(\d{1,2})\b", "$3$2$1", "", 1)
If RegExMatch(str, "i)^\s*(?:(\d{4})([\s\-:\/])(\d{1,2})\2(\d{1,2}))?"
. "(?:\s*[T\s](\d{1,2})([\s\-:\/])(\d{1,2})(?:\6(\d{1,2})\s*(?:(Z)|(\+|\-)?"
. "(\d{1,2})\6(\d{1,2})(?:\6(\d{1,2}))?)?)?)?\s*$", i)
d3 := i1, d2 := i3, d1 := i4, t1 := i5, t2 := i7, t3 := i8
Else If !RegExMatch(str, "^\W*(\d{1,2}+)(\d{2})\W*$", t)
RegExMatch(str, "i)(\d{1,2})\s*:\s*(\d{1,2})(?:\s*(\d{1,2}))?(?:\s*([ap]m))?", t)
, RegExMatch(str, e2, d)
f = %A_FormatFloat%
SetFormat, Float, 02.0
d := (d3 ? (StrLen(d3) = 2 ? 20 : "") . d3 : A_YYYY)
. ((d2 := d2 + 0 ? d2 : (InStr(e2, SubStr(d2, 1, 3)) - 40) // 4 + 1.0) > 0
? d2 + 0.0 : A_MM) . ((d1 += 0.0) ? d1 : A_DD) . t1
+ (t1 = 12 ? t4 = "am" ? -12.0 : 0.0 : t4 = "am" ? 0.0 : 12.0) . t2 + 0.0 . t3 + 0.0
SetFormat, Float, %f%
Return, d
}
Concerning: your comment:
(3) Your RenameSelectedFile call (line 12) is bad. You are calling it with parameters Components and Date, but neither of those has been assigned a value. If you don't understand how functions are called and what the parameters mean, you should study the doc here:
I am trying to understand why in your proposal:
#a43022090 you call the function with Components and Date. I supposed that it is because the buttons related to the GUI which use date and the various files components which is not the case for the msgbox approach.
Regards,
Luis.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you very much Joe for this last comment.
Have a great week!
Regards,
Luis.
Have a great week!
Regards,
Luis.
You're welcome, Luis, you have a great week, too! Regards, Joe
Some comments on that list of special characters:
(1) The chars '/', '?', and '*' can never be in your selected file(s), because they are invalid in file names.
(2) The space char is not in your special chars list, but in your example below (Test-file-name-9.pdf), the spaces are changed to hyphens, so I presume you want the space char in the special chars list...right?
(3) If you replace all '.' chars, the file will not have a file extension. Would you like to keep the last dot so that the extension remains?
(4) If you replace '\' chars, you'll destroy the file path. Do you really want to do that? Remember, the backslash is invalid in a file name, except in paths.
Btw, here are the characters that are invalid in a file name:
< (less than)
> (greater than)
: (colon) - except in path
" (double quote)
/ (forward slash)
\ (backslash) - except in path
| (vertical bar or pipe)
? (question mark) - except as wildcard
* (asterisk) - except as wildcard
Regards, Joe