Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Function: Get next/free Available File Name


  • Please log in to reply
4 replies to this topic
toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
GetAvailableFileNameThis function returns the next free/available file name.

The function returns 0 when an error occured and ErrorLevel will contain a detailed error message.

The function replaces the "#" in the given file name with a number (with leading zeros). The number starts from 1 or from any given StartID. E.g. ###.ahk with StartID = 12 will result in 012.ahk, 013.ahk, 014.ahk, etc.

All formats are possible, e.g. x#.#y##z.ahk with StartID = 4199 will result in x4.1y99z.ahk, x4.2y00z.ahk, x4.2y01z.ahk, etc.

The path for the file can be specified or the current directory will be used.

The function is 90 lines of code while the most part is error handling. Without these error handling the function is only 16 lines. I added the "pure" function below.
;######################## Testing

Eval( GetAvailableFileName( A_ScriptName ))      ; should be error
Eval( GetAvailableFileName( "xyz.ahk" ))         ; ok
Eval( GetAvailableFileName( "xy#z.ahk" ))        ; ok
Eval( GetAvailableFileName( "x#y#z.ahk" ))       ; ok
Eval( GetAvailableFileName( "xy##z.ahk" ))       ; ok
Eval( GetAvailableFileName( "x#.#y##z.ahk" ))    ; ok
Eval( GetAvailableFileName( "####.ahk" ))        ; ok
Eval( GetAvailableFileName( "xy##z.ahk", "C:\" ))              ; ok
Eval( GetAvailableFileName( "xy##z.ahk", "C:\Windows" ))       ; ok
Eval( GetAvailableFileName( "xy##z.ahk", "C:\XYZ0125RET\" ))   ; should be error
Eval( GetAvailableFileName( "xy##z.ahk", "", 5 ))              ; ok
Eval( GetAvailableFileName( "xy##z.ahk", "", 115 ))            ; should be error
Eval( GetAvailableFileName( "xy##z.ahk", "", 33 ))             ; ok
Eval( GetAvailableFileName( "xy##z.ahk", "", 33.3 ))           ; ok
Msgbox, % Eval("")                                             ;%
Return

Eval(FileName)
{
  static MsgTxt
  If FileName = 0
    MsgTxt = %MsgTxt%Error: %ErrorLevel%`n`n
  Else
    MsgTxt = %MsgTxt%%FileName%`n`n
  Return  MsgTxt
}

;######################## Func: GetAvailableFileName

GetAvailableFileName( GivenFileName, GivenPath = "", StartID = 1 )
{ 
  ;check if GivenPath exist and add "\" if necessary
  If GivenPath is not space
    {
      StringRight, LastChar, GivenPath, 1
      If ( LastChar <> "\" )
        GivenPath = %GivenPath%\
      If ( InStr(FileExist(GivenPath), "D") = 0 )
        {
          ErrorLevel = The given path >%GivenPath%< doesn't exist.
          Return 0
        }
    }

  ;check if StartID is reasonable
  If ( StartID < 0 Or Mod(StartID, 1) <> 0 )
    {
      ErrorLevel =
        (LTrim
           The StartID >%StartID%< is smaller then zero or not an integer.
           It has to be a positive integer.
        )
      Return 0
    }

  ;split GivenFileName with #
  StringSplit, NameArray, GivenFileName, #
  
  ;if GivenFileName doesn't contain # ...
  If NameArray0 < 2
    {
      ;check if GivenFileName exists
      If FileExist(GivenPath . GivenFileName)
        {
          ErrorLevel =
            (LTrim
              The given file >%GivenFileName%< does exist
              in path >%GivenPath%<.
              (if path is empty, it's the path of the script/exe)
            )
          Return 0
        }
      Else
          Return GivenPath . GivenFileName
    }

  ;check if StartID isn't too large
  If ( StrLen(StartID) > NameArray0 - 1 )
    {
      ErrorLevel =
        (LTrim
           The StartID >%StartID%< is too large
           for the filename >%GivenFileName%<.
        )
      Return 0
    }
  
  ;Search from StartID ...
  Loop 
    { 
      Number := A_Index + StartID - 1
             
      ;untill number is too large ...
      If ( StrLen(Number) > NameArray0 - 1 )
        {
          ErrorLevel =
            (LTrim
              All files exist for >%GivenFileName%<
              with all # between %StartID% and %Number%.
            )
          Return 0
        }

      ;otherwise fill number with leading zeros
      Loop, % NameArray0 - 1 - StrLen(Number) ;%
          Number = 0%Number% 
      
      ;split number in an array
      StringSplit, NumberArray, Number
      
      ;mix and concatenate the names array with the numbers array
      FileName =
      Loop, %NameArray0%
          FileName := FileName . NameArray%A_Index% . NumberArray%A_Index%
      
      ;check if GivenFileName doesn't exist
      If not FileExist(GivenPath . FileName)
          Return GivenPath . FileName
     } 
}

Without error handling
GetAvailableFileName( GivenFileName, GivenPath = "", StartID = 1 ) 
{ 
  StringSplit, NameArray, GivenFileName, # 
  Loop 
    { 
      Number := A_Index + StartID - 1 
      Loop, % NameArray0 - 1 - StrLen(Number) ;% 
          Number = 0%Number% 
      StringSplit, NumberArray, Number 
      FileName = 
      Loop, %NameArray0% 
          FileName := FileName . NameArray%A_Index% . NumberArray%A_Index% 
      If not FileExist(GivenPath . FileName) 
          Return GivenPath . FileName 
     } 
}

Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
With this function it is pretty simple to create a shortcut that creates a small file from code that has been marked in the AHK forum (browser) and open them in an editor. Since the file will have already the correct suffix the syntaxhighlightning is immediatly active (at least in the case of UltraEdit).
~!c::

  IfWinActive, AutoHotkey Community ::

    {

      ClipBoard =

      Send, ^c

      FileNameAHKCopy := GetAvailableFileName("Bearbeiten##.ahk","C:\AHK\")

      If ( ClipBoard <> "" And FileNameAHKCopy <> 0 )

        {

          FileAppend, %ClipBoard%, %FileNameAHKCopy%

          Run, %ExeEdit% "%FileNameAHKCopy%"

          ClipBoard =

        }

    }

Return

Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
Added the function without error handling to the first post.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

Sevir
  • Guests
  • Last active:
  • Joined: --
I know I'm doing something wrong, I copied the script exactly into my existing Autohotkey.ahk, but nothing. Does it need it's own script?
When it works, do I just save a file as FileName ##v#.extension?
Does it need to be in a specific directory?

Forgive my ignorance, but I really want this script and can't figure it out myself.

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
I find this a very useful function which I use myself, never did thank Toralf so Thanks Toralf :D

Try the test script below and run it a few times, perhaps it will help you understand how it works, look at the more complex examples above if you understand this one.
test=
(
this
is
a
test
file
)

FileAppend, %Test%, % GetAvailableFileName("file##.txt") ;or
;FileName:=GetAvailableFileName("file##.txt")
;FileAppend, %Test%, %FileName%

GetAvailableFileName( GivenFileName, GivenPath = "", StartID = 1 )
{
  StringSplit, NameArray, GivenFileName, #
  Loop
    {
      Number := A_Index + StartID - 1
      Loop, % NameArray0 - 1 - StrLen(Number) ;%
          Number = 0%Number%
      StringSplit, NumberArray, Number
      FileName =
      Loop, %NameArray0%
          FileName := FileName . NameArray%A_Index% . NumberArray%A_Index%
      If not FileExist(GivenPath . FileName)
          Return GivenPath . FileName
     }
}
Run it a few times in a row and you should see file01.txt file02.txt etc. The function will look in the target directory and will try to figure out what the next free filename is so you can use that to save data from your AHK script or copy/move a file without overwriting it.