Page 1 of 3

CreateDirectory() recursively or CreatePath()

Posted: Fri Mar 10, 2017 3:53 pm
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")

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Mar 10, 2017 4:09 pm
by davido
+1

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Mar 10, 2017 5:20 pm
by Fredi
+1

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Mar 10, 2017 5:36 pm
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

Re: CreateDirectory() recursively or CreatePath()

Posted: Sat Mar 11, 2017 1:06 am
by Dude
For Windows only:

Code: Select all

SHCreateDirectory_(0,"C:\Temp\A\B\C\")

Re: CreateDirectory() recursively or CreatePath()

Posted: Sat Mar 11, 2017 4:35 am
by collectordave
+1 for sicro

Take the procedure from the archive.

Re: CreateDirectory() recursively or CreatePath()

Posted: Sat Mar 11, 2017 5:08 am
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

Re: CreateDirectory() recursively or CreatePath()

Posted: Sat Mar 11, 2017 11:14 am
by IdeasVacuum
Nice one Fangbeast

Windows Error Codes

#ERROR_CANCELLED = 1223 (0x4C7)

Re: CreateDirectory() recursively or CreatePath()

Posted: Sat Mar 11, 2017 11:58 am
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.

Re: CreateDirectory() recursively or CreatePath()

Posted: Sat Mar 11, 2017 12:45 pm
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.

Re: CreateDirectory() recursively or CreatePath()

Posted: Sat Mar 11, 2017 1:53 pm
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??

Re: CreateDirectory() recursively or CreatePath()

Posted: Sat Mar 11, 2017 2:21 pm
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

Re: CreateDirectory() recursively or CreatePath()

Posted: Thu Jan 07, 2021 11:09 am
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

Re: CreateDirectory() recursively or CreatePath()

Posted: Thu Jan 07, 2021 2:19 pm
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

Re: CreateDirectory() recursively or CreatePath()

Posted: Thu Jan 07, 2021 2:32 pm
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