AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Change file extension

 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
a_h_k



Joined: 02 Feb 2008
Posts: 626

PostPosted: Fri May 29, 2009 5:23 pm    Post subject: Change file extension Reply with quote

Latest code is at bottom of this thread

This is just a basic script which allows the extension of a file (as well as filename) to be changed. I created it due to being fed-up with having to show ext's whenever wanted to change the file type (i keep extensions hidden in explorer)

. . . . . -----> . . . . .


Code:
#NoEnv
SetTitleMatchMode, 3      ;Exact
SetKeyDelay, 0
CoordMode, Mouse, Screen
#NoTrayIcon


; Convert 8.3 name (passed format) into LONG (Windows) name  (for use with FileMove)
Loop, %1%
{
  long_pathname_from := A_LoopFileLongPath
  long_path_from := A_LoopFileDir
  long_filename_ext_from := A_LoopFileName
}
pathname_from := long_pathname_from
path_from := long_path_from
filename_ext_from := long_filename_ext_from


; Launch separate thread (which will do stuff while CURRENT (main) thread is "stuck" in InputBox)
SetTimer, Highlight_Extension, On   ;Go there now, & start waiting (for InputBox to exist)


InputBox, altered_name_ext, Change Filename/Extension, Enter new filename.ext,, 250, 125,,,,,%filename_ext_from%


If ErrorLevel = 1   ;Press Esc key on keyboard
  Exit


path_to := path_from
pathname_to = %path_to%\%altered_name_ext%


FileMove, %pathname_from%, %pathname_to%

ExitApp

;-----------------------------------------------
Highlight_Extension:
  SetTimer, Highlight_Extension, Off   ;Only allows 1 execution of this routine
  Sleep, 7   ;Give sufficient time for InputBox to be created

  ; Ensure Input-Box exists
  IfWinNotExist, Change Filename/Extension
    Exit         ; No InputBox opened (for some unknown reason), so exit script
  IfWinNotActive, Change Filename/Extension
    {
    WinActivate, Change Filename/Extension
    WinWaitActive, Change Filename/Extension
    }

  Send {End}{Shift Down}{Left}{Left}{Left}{Shift Up}      ;Highlights just the extension (.abc)
Return
;-----------------------------------------------


To try it out:
1) Compile the source
2) Place .exe in (say) C..Program Files..Change Extension
3) Add the context-menu entry (alter registry, as follows)




* One issue is that it doesn't work for shortcut files. Any ideas??


Last edited by a_h_k on Tue Jun 23, 2009 3:19 am; edited 4 times in total
Back to top
View user's profile Send private message Visit poster's website
jaco0646



Joined: 07 Oct 2006
Posts: 3113
Location: MN, USA

PostPosted: Sun May 31, 2009 2:01 am    Post subject: Re: Change file extension Reply with quote

Your code works well and your documentation is great: a very nice pictorial. Smile

a_h_k wrote:
I created it due to being fed-up with having to show ext's whenever wanted to change the file type (i keep extensions hidden in explorer)
I feel the same way. I wanted to make something like this a few months ago, but the problem I couldn't resolve is how to Rename desktop files, without moving icons. I still haven't found a solution for that one. Mad

A few notes if you're interested:
You commented that converting from 8.3 file names was for the benefit of the FileMove command. All file commands should work with 8.3 short paths and file names; so you only need the long name to display for editing.
Creating a custom Gui in place of the InputBox is quite easy. It erases the need for a timer and is more versatile. Here's one example.
Code:
#SingleInstance force
#NoTrayIcon
#NoEnv
CoordMode, Mouse

MouseGetPos,X,Y
Loop, %1%
 path := A_LoopFileLongPath
If !path
 ExitApp
SplitPath,path,,dir,ext,name
Gui, Add, Edit, vname -TabStop, %name%
Gui, Add, Edit, vext x+0, %ext%
Gui, Add, Button, Default -TabStop, Rename
Gui, Show, x%X% y%Y%, *.*
return

ButtonRename:
Gui, Submit
FileMove,% path,% dir "\" name "." ext
If ErrorLevel
 MsgBox,16,*.*,Error: "%path%" could not be renamed.
GuiClose:
ExitApp
You may also have a look at the "Run only once" option of SetTimer, which could save you a line in your code, and the WinWait command, which could replace Sleep with more precision.

Finally, a way to use the program without needing any registry edits is to place the compiled EXE in the Send To folder (e.g. C:\Documents and Settings\UserName\SendTo) and execute it from the Send To submenu of the context menu.
Back to top
View user's profile Send private message Visit poster's website
ManaUser



Joined: 24 May 2007
Posts: 1121

PostPosted: Sun May 31, 2009 3:07 am    Post subject: Reply with quote

I can't imagine why someone would want to hide file extensions, but if I did, that would be a great way to mitigate some of the annoyance.
Back to top
View user's profile Send private message
a_h_k



Joined: 02 Feb 2008
Posts: 626

PostPosted: Sun May 31, 2009 4:50 am    Post subject: Reply with quote

ManaUser wrote:
I can't imagine why someone would want to hide file extensions, but if I did, that would be a great way to mitigate some of the annoyance


Why i do so, is
1) Looks nicer/simpler (less clutter) Smile
2) When renaming file, no need to worry about leaving ext there (not overwriting - which i used to do all the time (annoying! Mad ))

Also, i pretty much know what most of my common file extensions are (by their icons) Wink
Back to top
View user's profile Send private message Visit poster's website
a_h_k



Joined: 02 Feb 2008
Posts: 626

PostPosted: Sun May 31, 2009 5:09 am    Post subject: Reply with quote

Thanks for your imput jaco0646 - very useful

Its been several months since i wrote this script, but think maybe what i meant by "for use with FileMove" was not that FileMove required long filenames, but that i use long filenames in the variables used by the FileMove statement (just sth to remind me why i was converting 8.3 into long). This reason being mainly (as you said) for display in message box, but also as i felt it was easier to use overall than staying with 8.3 (ie convert all into long, then that's it .. no need for any more conversions (eg 8.3 --> display filename)). But i will erase this text in next version

I have implemented "run only once" option of SetTimer (guess i didn't see that in the help!)

I have replaced "Sleep" with "WinWait"

Now leaves path as 8.3

Recreated code to calculate/extract path & filename (from pathname)

Fixed a bug concerning pathnames containing spaces

Concerning the reg entries, i already created a .reg file, but it's only for XP (the instructions allow people with other OS's to alter it to fit). Maybe later i'll create an installer script to detect Windows type, & add the keys to registry

I initially considered putting in SendTo menu, but decided to put in root of context menu, as i use the extension quite a lot (so saves time by being in root)

Code:
#NoEnv
SetTitleMatchMode, 3      ;Exact
SetTitleMatchMode, Slow
SetKeyDelay, 0
AutoTrim, Off
#NoTrayIcon


; Re-join passed parameter-parts into single parameter (if path has space/s)
pathname_from =
space_to_add =
Loop, %0%
{
  part_to_add := %A_Index%
  pathname_from = %pathname_from%%space_to_add%%part_to_add%
  space_to_add = %A_Space%
}


; Split pathname into path + filename.ext
;
StringGetPos, pos_of_last_slash, pathname_from, \, r1      ;Find last "\"
;
filename_ext_len := StrLen(pathname_from) - pos_of_last_slash - 1
StringRight, filename_ext_from, pathname_from, filename_ext_len
;
path_len := pos_of_last_slash
StringLeft, path_from, pathname_from, path_len


; Launch separate thread (which will do stuff while CURRENT (main) thread is "stuck" in InputBox)
SetTimer, Highlight_Extension, -1   ;-1 = execute once only + go there now (& start waiting for InputBox to exist)


; Input box
InputBox, altered_name_ext, Change Filename/Extension, Enter new filename.ext,, 250, 125,,,,,%filename_ext_from%
If ErrorLevel = 1   ;Press Esc key on keyboard
  Exit


; Change the filename/extension
path_to := path_from
pathname_to = %path_to%\%altered_name_ext%
FileMove, %pathname_from%, %pathname_to%


ExitApp

;-----------------------------------------------

Highlight_Extension:
  WinWait, Change Filename/Extension,,2      ;Gives InputBox 2 secs to be created (eg system on a "go-slow")

  ; Ensure Input-Box exists
  If ErrorLevel = 1
    ExitApp   ;No InputBox opened (for some unknown reason), so exit script
  Else
    {       ;InputBox opened
      IfWinNotActive, Change Filename/Extension
      {
        WinActivate, Change Filename/Extension
        WinWaitActive, Change Filename/Extension
      }
    }

  Send {End}{Shift Down}{Left}{Left}{Left}{Shift Up}      ;Highlights just the extension (.abc)
Return

;-----------------------------------------------
Back to top
View user's profile Send private message Visit poster's website
a_h_k



Joined: 02 Feb 2008
Posts: 626

PostPosted: Sun May 31, 2009 11:34 am    Post subject: Modified Reply with quote

Now back to a shortened version of Loop (since forgot that had to convert filename from 8.3 to long anyway (for display))

Was
Code:
; Split pathname into path + filename.ext
;
StringGetPos, pos_of_last_slash, pathname_from, \, r1      ;Find last "\"
;
filename_ext_len := StrLen(pathname_from) - pos_of_last_slash - 1
StringRight, filename_ext_from, pathname_from, filename_ext_len
;
path_len := pos_of_last_slash
StringLeft, path_from, pathname_from, path_len

Now
Code:
; Extract (long) file variables from (8.3) pathname
Loop, %pathname_from%
{
  path_from = %A_LoopFileDir%
  filename_ext_from = %A_LoopFileName%
}

Code
Code:
#NoEnv
SetTitleMatchMode, 3      ;Exact
SetTitleMatchMode, Slow
SetKeyDelay, 0
AutoTrim, Off
#NoTrayIcon


; Re-join passed parameter-parts into single parameter (if path has space/s)
pathname_from =
space_to_add =
Loop, %0%
{
  part_to_add := %A_Index%
  pathname_from = %pathname_from%%space_to_add%%part_to_add%
  space_to_add = %A_Space%
}


; Extract (long) file variables from (8.3) pathname
Loop, %pathname_from%
{
  path_from = %A_LoopFileDir%
  filename_ext_from = %A_LoopFileName%
}


; Launch separate thread (which will do stuff while CURRENT (main) thread is "stuck" in InputBox)
SetTimer, Highlight_Extension, -1   ;-1 = execute once only + go there now (& start waiting for InputBox to exist)


; Input box
InputBox, altered_name_ext, Change Filename/Extension, Enter new filename.ext,, 250, 125,,,,,%filename_ext_from%
If ErrorLevel = 1   ;Press Esc key on keyboard
  Exit


; Change the filename/extension
path_to := path_from
pathname_to = %path_to%\%altered_name_ext%
FileMove, %pathname_from%, %pathname_to%


ExitApp

;-----------------------------------------------

Highlight_Extension:
  WinWait, Change Filename/Extension,,2      ;Gives InputBox 2 secs to be created (eg system on a "go-slow")

  ; Ensure Input-Box exists
  If ErrorLevel = 1
    ExitApp   ;No InputBox opened (for some unknown reason), so exit script
  Else
    {       ;InputBox opened
      IfWinNotActive, Change Filename/Extension
      {
        WinActivate, Change Filename/Extension
        WinWaitActive, Change Filename/Extension
      }
    }

  Send {End}{Shift Down}{Left}{Left}{Left}{Shift Up}      ;Highlights just the extension (.abc)
Return

;-----------------------------------------------
Back to top
View user's profile Send private message Visit poster's website
a_h_k



Joined: 02 Feb 2008
Posts: 626

PostPosted: Sun May 31, 2009 1:01 pm    Post subject: Reply with quote

Now here's a bit of a tricky problem:

It's to do with the "Re-join passed parameter-parts ..." code that i added

This is the file to have it's name/ext changed: Change Extension___v.exe
(it can be ANY file with "multiple" spaces in it's pathname (folders or filename part) (eg "Chng__Ext.exe"))

When the file is here:
C:\Program Files\MINE\Change Extension\Change Extension___v.exe
|. . . 1 . . . | |. . . . . . . 2 . . . . . .| |. . . . . 3 . . . . . . . | |. . .4. . .|......|. 8 .|

But since %0% + %1% = 8.3 (& why not %2%...??) we actually get this passed
C:\PROGRA~1\MINE\Change Extension\Change Extension v.exe
|. . . . . . . . . . 1 . . . . . . . . . .| |. . . . . . 2 . . . . . . | |. . . 3. . .| |. 4 .|
%0% = 4
%1% = C:\PROGRA~1\MINE\Change
%2% = Extension\Change
%3% = Extension
%4% = v.exe
and lose the "___" before the "v" ("___" = 4 spaces (lost in this post also!)) Sad

But when i placed the file here:
K:\Program Files\MINE\Change Extension\Change Extension___v.exe
%0% = 1
%1% = K:\PROGRA~1\MINE\CHANGE~2\CHANGE~1.EXE
it works "correctly"! Confused

So the Q is, why does it "play up" just when file is in C: drive? (all the other drives worked fine)
Back to top
View user's profile Send private message Visit poster's website
Lexikos



Joined: 17 Oct 2006
Posts: 7295
Location: Australia

PostPosted: Mon Jun 01, 2009 12:41 am    Post subject: Reply with quote

If you add "quote marks" around the %1 in the registry, the entire filename will be put in %1% and you won't need to "re-join" any parameters. If you use "%L" instead of "%1", you should get the long filename every time.
Back to top
View user's profile Send private message Visit poster's website
a_h_k



Joined: 02 Feb 2008
Posts: 626

PostPosted: Tue Jun 02, 2009 6:06 am    Post subject: Reply with quote

Great Lexikos !! Very Happy
So now i can rid that bit of code at top & no problems now!
(used "%1" in registry value)
And for some reason the %1% param is now all long, so don't need to use the "%L" (?)

Anyway here's the code now
Code:
#NoEnv
SetTitleMatchMode, 3      ;Exact
SetTitleMatchMode, Slow
SetKeyDelay, 0
AutoTrim, Off
#NoTrayIcon


pathname_from = %1%


; Extract path + filename.ext from (long) pathname
Loop, %pathname_from%
{
  path_from = %A_LoopFileDir%
  filename_ext_from = %A_LoopFileName%
}


; Launch separate thread (which will do stuff while CURRENT (main) thread is "stuck" in InputBox)
SetTimer, Highlight_Extension, -1   ;-1 = execute once only + go there now (& start waiting for InputBox to exist)


; Input box
InputBox, altered_name_ext, Change Filename/Extension, Enter new filename.ext,, 250, 125,,,,,%filename_ext_from%
If ErrorLevel = 1   ;Press Esc key on keyboard
  Exit


; Change the filename/extension
path_to := path_from
pathname_to = %path_to%\%altered_name_ext%
FileMove, %pathname_from%, %pathname_to%


ExitApp

;-----------------------------------------------

Highlight_Extension:
  WinWait, Change Filename/Extension,,2      ;Gives InputBox 2 secs to be created (eg system on a "go-slow")

  ; Ensure Input-Box exists
  If ErrorLevel = 1
    ExitApp   ;No InputBox opened (for some unknown reason), so exit script
  Else
    {       ;InputBox opened
      IfWinNotActive, Change Filename/Extension
      {
        WinActivate, Change Filename/Extension
        WinWaitActive, Change Filename/Extension
      }
    }

  Send {End}{Shift Down}{Left}{Left}{Left}{Shift Up}      ;Highlights just the extension (.abc)
Return

;-----------------------------------------------
Back to top
View user's profile Send private message Visit poster's website
Zizou



Joined: 16 Nov 2008
Posts: 32

PostPosted: Mon Jun 22, 2009 6:16 am    Post subject: Reply with quote

I've made some little modifications:
  • More reliability:
    • For extensions larger (and shorter) than 3 characters (e.g., 7z, au, js, 3gp2, aiff, h264, html, tiff, jpeg, mpeg, xvid, gadget, torrent)
    • Doesn't need the InputBox to be Active (very unlikely) for highlighting the extension.
    • For Window recognizing if a "Change Filename/Extension" InputBox is already opened.
  • A bit shorter.
  • And it automatically adds an option in Context Menu the first time it's opened. If EXE is moved or renamed, just have to run it again for updating the registry.
Code:
#NoEnv
#NoTrayIcon
SetKeyDelay, -1
SetTitleMatchMode, 3

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;@ Create an option in Explorer Context Menu
RegWrite, REG_SZ, HKEY_CLASSES_ROOT, *\Shell\Change File Extension\command,, "%A_ScriptFullPath%" "`%1"

;@ Split File Path
FullFilePath = %1%
SplitPath, FullFilePath, FileName, FileDir, FileExt
StringLen, ExtLen, FileExt

;@ Launch a Label while continue running the other task
SetTimer, HighlightExt, -1
InputBox, nFileName, Change Filename/Extension, Enter new filename and/or extension,, 250, 125,,,,,%FileName%
If ErrorLevel
  Exit
FileMove, %FileDir%\%FileName%, %FileDir%\%nFileName%
Exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;@ Labels
HighlightExt:
WinWaitActive, Change Filename/Extension ahk_class #32770,, 2
If ErrorLevel
   Exit
ControlSend, Edit1, {End}+{Left %ExtLen%}, Change Filename/Extension ahk_class #32770
Return

Thanks to a_h_k.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group