How to create a new folder with a unique name

Just starting out? Need help? Post your questions and find answers here.
itto
User
User
Posts: 12
Joined: Fri Jul 27, 2012 8:12 pm
Location: Italy
Contact:

How to create a new folder with a unique name

Post by itto »

Hi there,

I have the need to create a new folder, no matter what name, just like you would normally do with the OS "new folder" menu entry.

Normally windows creates a new folder named "new folder", and if a folder with that name already exists, an increasing number is added in parentheses afterwards, like "New folder (2)", ecc.

How can I check what is the last free name (with number) available in a specified folder, given the folder name?

I was thinking about checking one by one the files of the directory, until all folders starting with the string "New folder (N)" are checked, then just add +1 to the last N checked.

But this could be a problem for folders with thousand of elements, I don't want to waste resources.

Anyone has a better idea? Perhaps some API entries?

Thanks :)
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to create a new folder with a unique name

Post by IdeasVacuum »

Use ExamineDirectory() to list all folders within a folder and then use a regular expression (or find string combo) on each folder name in the list to find post-fixed numbers in parentheses.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
itto
User
User
Posts: 12
Joined: Fri Jul 27, 2012 8:12 pm
Location: Italy
Contact:

Re: How to create a new folder with a unique name

Post by itto »

Ok, this is the solution I came up with, except I chose to match the whole folder name. I was hoping for a OS command to let it create the folder for you, like you would do normally using the OS menus.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to create a new folder with a unique name

Post by IdeasVacuum »

Hmm, possibly using a little script via RunProgram()
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: How to create a new folder with a unique name

Post by ts-soft »

I would use a GUID as Directory Name. The code to create a GUID can you extract from this source:
http://www.purebasic.fr/english/viewtop ... 00#p381100
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
VoSs2o0o
User
User
Posts: 24
Joined: Fri Aug 06, 2010 11:46 pm

Re: How to create a new folder with a unique name

Post by VoSs2o0o »

A Timestamp is enough....

Code: Select all

Dirname.s = Str(Date())
juror
Enthusiast
Enthusiast
Posts: 228
Joined: Mon Jul 09, 2007 4:47 pm
Location: Courthouse

Re: How to create a new folder with a unique name

Post by juror »

VoSs2o0o wrote:A Timestamp is enough....

Code: Select all

Dirname.s = Str(Date())
Does NOT guarantee uniqueness.
itto
User
User
Posts: 12
Joined: Fri Jul 27, 2012 8:12 pm
Location: Italy
Contact:

Re: How to create a new folder with a unique name

Post by itto »

Thank you for your replies guys! The problem is that I am creating this folder as a direct consequence of the user action on the file system (I'm enhancing the OS file system commands via additional contextual menus when browsing files and folders), so the name is going to be user friendly and as close as possible as the current OS default name (to not create confusion).

The best would be for the name to be exactly identical to the default system new folder name (thus taking into account the OS language), but I think this is impossible without an OS api or knowing where the default folder name variable is stored in the OS.

edit

by the way thanks ts-soft for the GUID code, it's wonderful and I'll surely use it in many applications! :o
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to create a new folder with a unique name

Post by IdeasVacuum »

where the default folder name variable is stored in the OS.
Most likely, that would be stored in the Registry, if it is stored - though I think it probably isn't because it doesn't apply system-wide. Different paths can contain identical folder names (New Folder, New Folder (1) New Folder (2) etc, not the space char between the name and the postfix). It's not impossible to keep a record of it but there isn't a good reason to.

Edit: There is no var. If you create some new folders with any name other than New Folder, then re-name them in sequence, New Folder, New Folder (1) New Folder (2), then create another new folder and let the system name it, the system creates New Folder (3). So, your code can safely create these too.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
kenmo
Addict
Addict
Posts: 2033
Joined: Tue Dec 23, 2003 3:54 am

Re: How to create a new folder with a unique name

Post by kenmo »

Something like this?

Code: Select all

Procedure.s UniqueFolder(BasePath.s = "")
  Protected n.i = 1
  
  If (BasePath = "")
    BasePath = GetCurrentDirectory()
  EndIf
  
  While (Not CreateDirectory(BasePath + "New Folder (" + Str(n) + ")"))
    n + 1
  Wend
  
  ProcedureReturn BasePath + "New Folder (" + Str(n) + ")"
EndProcedure

Folder.s = UniqueFolder()

Debug "Created: " + Folder
;DeleteDirectory(Folder, "")
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: How to create a new folder with a unique name

Post by RASHAD »

Using MAC Address

Code: Select all

wsa.WSADATA
*host.HOSTENT

nSize = 32
lpBuffer$ = Space(nSize)
GetComputerName_(@lpBuffer$,@nSize)
If WSAStartup_((1<<8|1), wsa.WSADATA) = #NOERROR
    *host.HOSTENT = gethostbyname_(lpBuffer$)
    WSACleanup_()
    If *host
      IP$ = PeekS(inet_ntoa_(PeekL(PeekL(*host\h_addr_list))))
    EndIf
EndIf

n = 6
Dim MacAddr.b(6)
If SendARP_(inet_addr_(IP$), 0, @MacAddr(0), @n) = #NO_ERROR
  For i = 0 To 5
    MAC$ + RSet(Hex(MacAddr(i)&255),2,"0") 
  Next
EndIf

Txt$ = "F:\"+MAC$
CreateDirectory(Txt$)

Egypt my love
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: How to create a new folder with a unique name

Post by Danilo »

Code: Select all

Procedure.s GetNewFolderName()
    Protected index, shell32, name.s
    If OSVersion() >= #PB_OS_Windows_Vista
        index = 16859 ;"New Folder"
    Else
        index = 30320 ;"New Folder"
    EndIf
    
    shell32 = LoadLibrary_("shell32.dll")
    If shell32
        name = Space(1024)
        LoadString_(shell32,index,@name,1024)
        
        FreeLibrary_(shell32)
    EndIf
    ProcedureReturn name
EndProcedure

MessageRequester("New Folder", GetNewFolderName() )


Procedure.s GetUniqueDirectoryName(path.s, template.s)
    Protected fileName.s = path.s+template
    Protected fileNameAddon.s = ""
    For i = 1 To $FFFFFF
        size = FileSize(fileName+fileNameAddon)
        If size = -1
            Break
        Else
            fileNameAddon = " ("+Str(i+1)+")"
        EndIf
    Next
    ProcedureReturn fileName+fileNameAddon
EndProcedure

MessageRequester("New Folder", GetUniqueDirectoryName( "c:\", GetNewFolderName() ) )
Tested:
Win7 64bit english: "New Folder", "New Folder (2)", ...
WinXP Pro 32bit German: "Neuer Ordner", "Neuer Ordner (2)", ...
User avatar
ultralazor
Enthusiast
Enthusiast
Posts: 186
Joined: Sun Jun 27, 2010 9:00 am

Re: How to create a new folder with a unique name

Post by ultralazor »

Code: Select all

Procedure.s maked()
  Protected.l fhandle
  Protected.s ff$
  Repeat
    ff$="New Folder "+Str(Random(9999))
    fhandle=ExamineDirectory(#PB_Any,ff$,"*.*")
    If fhandle=0
      CreateDirectory(ff$)
      ProcedureReturn ff$
    Else
      FinishDirectory(fhandle)
    EndIf
  ForEver
EndProcedure
so many ideas so little time..
itto
User
User
Posts: 12
Joined: Fri Jul 27, 2012 8:12 pm
Location: Italy
Contact:

Re: How to create a new folder with a unique name

Post by itto »

Wow guys some really interesting code snippets are coming out here! Thanks!

@kenmo that's exactly the procedure I came up with and am currently using, which is really ok in the end.
Danilo wrote: Tested:
Win7 64bit english: "New Folder", "New Folder (2)", ...
WinXP Pro 32bit German: "Neuer Ordner", "Neuer Ordner (2)", ...
So this must be the same way Windows get the name of the new folder, this is awesome! the name changes according to the language of the OS! :D
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: How to create a new folder with a unique name

Post by Danilo »

itto wrote:
Danilo wrote: Tested:
Win7 64bit english: "New Folder", "New Folder (2)", ...
WinXP Pro 32bit German: "Neuer Ordner", "Neuer Ordner (2)", ...
So this must be the same way Windows get the name of the new folder, this is awesome! the name changes according to the language of the OS! :D
Yep. But the "magic numbers" changed in Vista.

Here is the code to get the "magic numbers" for the first code (requires UNICODE compilation!):

Code: Select all

;
; http://blogs.msdn.com/b/oldnewthing/archive/2004/01/30/65013.aspx
;
Macro MAKELANGID(p,s)
    ( ( (s)<< 10) | (p) )
EndMacro

Procedure.s FindStringResourceEx(hinst,uId.l, langId.l)
    ;// Convert the string ID into a bundle number
    ;*pwsz = 0
    hrsrc = FindResourceEx_(hinst, #RT_STRING,(uId / 16 + 1)&$FFFF,langId)
    If (hrsrc)
        hglob = LoadResource_(hinst, hrsrc);
        If (hglob)
            *pwsz.Unicode = LockResource_(hglob)
            If (*pwsz)
                *oldResPointer = *pwsz
                i = 0
                While i < (uId & 15)
                    *pwsz = *pwsz + 2 + (*pwsz\u * 2)
                    i+1
                Wend

                If *pwsz\u > 0
                    ret$ = PeekS(*pwsz + 2,*pwsz\u)
                EndIf
                ;UnlockResource_(*oldResPointer)
            EndIf
            FreeResource_(hglob)
        EndIf
    EndIf
    CompilerIf #PB_Compiler_Debugger
        ;If ret$
        ;    Debug ret$
        ;EndIf
    CompilerEndIf
    ProcedureReturn ret$
EndProcedure

Procedure.s FindStringResource(hinst, uId.l)
    ;(LANG_NEUTRAL, SUBLANG_NEUTRAL) = Language Neutral 
    ;(LANG_NEUTRAL, SUBLANG_DEFAULT) = User's Default Language 
    ProcedureReturn FindStringResourceEx(hinst, uId, MAKELANGID(#LANG_NEUTRAL, #SUBLANG_NEUTRAL))
EndProcedure

Procedure FindResourceStringId(resource_handle, string.s, langId)
    resource_id = -1

    For i = 0 To 65536 ;Step 16
        resource_string.s = FindStringResourceEx(resource_handle, i, langId)
        If resource_string
            If resource_string = string
                resource_id=i
                Debug resource_id
                Debug resource_string
                ;Break
            EndIf
        EndIf
        
    Next
    ProcedureReturn resource_id
EndProcedure

shell_handle  = LoadLibrary_("shell32.dll")
new_folder_id = FindResourceStringId(shell_handle, "New Folder", $409); // look for US English "New Folder" resource id.

Debug "-----"

If new_folder_id
    newfolder.s = FindStringResource(shell_handle, new_folder_id)
    ;MessageRequester("New Folder", newfolder )
    Debug newfolder

    Debug FindStringResourceEx(shell_handle, new_folder_id, MAKELANGID(#LANG_GERMAN   ,#SUBLANG_GERMAN) )
    Debug FindStringResourceEx(shell_handle, new_folder_id, MAKELANGID(#LANG_THAI     ,#SUBLANG_DEFAULT) )
    Debug FindStringResourceEx(shell_handle, new_folder_id, MAKELANGID(#LANG_ENGLISH  ,#SUBLANG_DEFAULT) )
    Debug FindStringResourceEx(shell_handle, new_folder_id, MAKELANGID(#LANG_FRENCH   ,#SUBLANG_DEFAULT) )

EndIf
This code is not useful in end-user programs! You can get the "magic numbers" with it
and use them with the LoadString_() method.
It requires some testing (f.e. in a virtual machine) if you get more than 1 magic number.
For example test:
- Win7/Vista English and WinXP Englisch
plus:
- Win7/Vista German/Other and WinXP German/Other

The line:

Code: Select all

new_folder_id = FindResourceStringId(shell_handle, "New Folder", $409); // look for US English "New Folder" resource id.
does not work if english MUI is not installed. It works only with currently installed languages (I tested with German/English/Thai).
Post Reply