CreateDirectory() recursively or CreatePath()

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

CreateDirectory() recursively or CreatePath()

Post by Lunasole »

For now CreateDirectory() works only if all parent path exists already, i.e. following code will not create folder "D:\1\2" if "D:\1" not created already:

Code: Select all

CreateDirectory("D:\1\2")

Would be useful if CreateDirectory() had #PB_FileSystem_Recursive flag, or just add some separated function like following:

Code: Select all

; Walks through given path and creates directories on the way
; Path$		full folder path
; RETURN:	1 on success, 0 if failed to create directory
Procedure CreatePath (Path$)
	Protected a, s$, t$
	Path$ = ReplaceString(Path$, "/", "\")
	Repeat
		a + 1
		t$ = StringField(Path$, a, "\") 
		
		If t$
			s$ + t$ + "\"
			
			If FileSize(s$) = -1 ; doesn't exists
				If Not CreateDirectory(s$)
					ProcedureReturn #false ; failed to recreate path
				EndIf
			EndIf
		Else
			Break
		EndIf
	Until s$ = ""
	ProcedureReturn #true
EndProcedure

; usage
CreatePath("D:\1\2")
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: CreateDirectory() recursively or CreatePath()

Post by davido »

+1
DE AA EB
Fredi
Enthusiast
Enthusiast
Posts: 143
Joined: Wed Jul 23, 2008 10:45 pm

Re: CreateDirectory() recursively or CreatePath()

Post by Fredi »

+1
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: CreateDirectory() recursively or CreatePath()

Post by Sicro »

+1

Alternatively, the procedure "CreatePath()" can be taken from the CodeArchiv:
https://github.com/SicroAtGIT/PureBasic ... tePath.pbi

@Lunasole: Your Code doesn't support paths like that:

Code: Select all

/home/user/myproject
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: CreateDirectory() recursively or CreatePath()

Post by Dude »

For Windows only:

Code: Select all

SHCreateDirectory_(0,"C:\Temp\A\B\C\")
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: CreateDirectory() recursively or CreatePath()

Post by collectordave »

+1 for sicro

Take the procedure from the archive.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: CreateDirectory() recursively or CreatePath()

Post by Fangbeast »

Code: Select all

Procedure.s MakeSureDirectoryPathExists(Directory.s)
  
  ErrorCode.i = SHCreateDirectory(#Null, Directory.s)
  
  Select ErrorCode.i
    Case #ERROR_SUCCESS               : Message.s = "Okay"                                           ; ResultCode = 0
    Case #ERROR_BAD_PATHNAME          : Message.s = "Bad directory path"                             ; ResultCode = 161
    Case #ERROR_FILENAME_EXCED_RANGE  : Message.s = "Directory path too long"                        ; ResultCode = 206
    Case #ERROR_FILE_EXISTS           : Message.s = "Directory already exists"                       ; ResultCode = 80
    Case #ERROR_ALREADY_EXISTS        : Message.s = "Directory already exists"                       ; ResultCode = 183
   ;Case #ERROR_CANCELLED             : Message.s = "The user canceled the operation."                ; ResultCode = ??. Not defined in compiler residents
  EndSelect
  
  ProcedureReturn Message.s
  
  ; Debug MakeSureDirectoryPathExists("c:\1\2\3\4\5\6")
  
EndProcedure
Amateur Radio, D-STAR/VK3HAF
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: CreateDirectory() recursively or CreatePath()

Post by IdeasVacuum »

Nice one Fangbeast

Windows Error Codes

#ERROR_CANCELLED = 1223 (0x4C7)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: CreateDirectory() recursively or CreatePath()

Post by Fangbeast »

IdeasVacuum wrote:Nice one Fangbeast

Windows Error Codes

#ERROR_CANCELLED = 1223 (0x4C7)
Rightyho. I just pilfered this code from the forum somewhere years ago and cleaned it up:):)

Thanks for that:)

I really should be codign something useful but it's been far too hot lately.
Amateur Radio, D-STAR/VK3HAF
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: CreateDirectory() recursively or CreatePath()

Post by Dude »

FangBeast's code is missing the underscore for the API call:

Code: Select all

Line 3: SHCreateDirectory() is not a function, array, list, map or macro.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: CreateDirectory() recursively or CreatePath()

Post by Fangbeast »

Dude wrote:FangBeast's code is missing the underscore for the API call:

Code: Select all

Line 3: SHCreateDirectory() is not a function, array, list, map or macro.
That's strange, never noticed that before but it works here and doesn't give that error. Am I going mad??
Amateur Radio, D-STAR/VK3HAF
User avatar
blueb
Addict
Addict
Posts: 1044
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: CreateDirectory() recursively or CreatePath()

Post by blueb »

Another way...

Code: Select all

;==================================================================
;
; Author:    ts-soft     
; Date:       March 5th, 2010
; Explain:
;	  modified version from IBSoftware (CodeArchiv)
;	  on vista and above check the Request for "User mode" or "Administrator mode" in compileroptions
;	 (no virtualisation!)
;==================================================================
Procedure ForceDirectories(Dir.s)
  Static tmpDir.s, Init
  Protected result
 
  If Len(Dir) = 0
    ProcedureReturn #False
  Else
    If Not Init
      tmpDir = Dir
      Init   = #True
    EndIf
    If (Right(Dir, 1) = "\")
      Dir = Left(Dir, Len(Dir) - 1)
    EndIf
    If (Len(Dir) < 3) Or FileSize(Dir) = -2 Or GetPathPart(Dir) = Dir
      If FileSize(tmpDir) = -2
        result = #True
      EndIf
      tmpDir = "" : Init = #False
      ProcedureReturn result
    EndIf
    ForceDirectories(GetPathPart(Dir))
    ProcedureReturn CreateDirectory(Dir)
  EndIf
EndProcedure

Debug ForceDirectories("Z:\aaa\bbb\") ; returns true if directory created
- It was too lonely at the top.

System : PB 6.10 LTS (x64) and Win Pro 11 (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
AZJIO
Addict
Addict
Posts: 1372
Joined: Sun May 14, 2017 1:48 am

Re: CreateDirectory() recursively or CreatePath()

Post by AZJIO »

It didn't work on Linux

For ForceDirectories() you need to change the line

Code: Select all

If (Right(Dir, 1) = "/") ; Linux, / instead of \
and in exceptional cases

Code: Select all

If (Len(Dir) < 2) ...
since the shortest path is "/a", i.e. 2 symbols
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: CreateDirectory() recursively or CreatePath()

Post by collectordave »

Code: Select all

  Procedure CheckCreatePath(Directory.s)
    
    Define BackSlashs.i,iLoop.i,Path.s,Temp.s
    
    BackSlashs = CountString(Directory, #PS$)
 
  Path =  ""
  For iLoop = 1 To BackSlashs + 1
    Temp = StringField(Directory.s, iLoop, #PS$)
    If StringField(Directory.s, iLoop+1, #PS$) > ""
      Path + Temp + #PS$
    Else
      Path + Temp
    EndIf
    CreateDirectory(Path)
  Next iLoop
  
EndProcedure 
Works on mac and windows and I think i tested it on linux as well
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
Bisonte
Addict
Addict
Posts: 1233
Joined: Tue Oct 09, 2007 2:15 am

Re: CreateDirectory() recursively or CreatePath()

Post by Bisonte »

Also from TS-Soft (this should work on all platforms) slightly modified :

Code: Select all

Procedure.i CreateDirectoryEx(DirectoryName.s, FileAttribute = #PB_Default) ; Erstellt Verzeichnis, inklusive Übergeordnete
  
  Protected i, c, tmp.s
  
  If Right(DirectoryName, 1) = #PS$
    DirectoryName = Left(DirectoryName, Len(DirectoryName) -1)
  EndIf
  c = CountString(DirectoryName, #PS$) + 1
  For i = 1 To c
    tmp + StringField(DirectoryName, i, #PS$)
    If FileSize(tmp) <> -2
      CreateDirectory(tmp)
    EndIf
    tmp + #PS$
  Next
  
  If FileAttribute <> #PB_Default
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      SetFileAttributes_(DirectoryName, FileAttribute)
    CompilerElse
      SetFileAttributes(DirectoryName, FileAttribute)
    CompilerEndIf
  EndIf
  
  If FileSize(DirectoryName) = -2
    ProcedureReturn #True
  EndIf
  
EndProcedure
Last edited by Bisonte on Fri Jan 08, 2021 10:39 am, edited 1 time in total.
PureBasic 6.10 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
English is not my native language... (I often use DeepL to translate my texts.)
Post Reply