Page 2 of 3

Re: CreateDirectory() recursively or CreatePath()

Posted: Thu Jan 07, 2021 3:47 pm
by NicTheQuick
Bisonte wrote:Also from TS-Soft (this should work on all platforms) slightly modified :

Code: Select all

    tmp + "\"
I wonder how that should work if there is a backslash right in the code.

Re: CreateDirectory() recursively or CreatePath()

Posted: Thu Jan 07, 2021 11:47 pm
by skywalk
This is what I use, and it is not recursive.

Code: Select all

;-! OS_PATH_SEPARATOR
; Not #OS_PATH_SEP$ due to ;BUG; PB v573 does not support @#OS_PATH_SEP$
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  Global.s OS_PATH_SEP$ = #PS$
CompilerElse
  Global.s OS_PATH_SEP$ = #NPS$
CompilerEndIf
Macro PB_CP
  ;ProgramFilename() + #COLON2$ + #PB_Compiler_File + #COLON2$ + #PB_Compiler_Procedure
  GetFilePart(#PB_Compiler_File, #PB_FileSystem_NoExtension) + "::" + #PB_Compiler_Procedure
EndMacro
Macro MRE(txt)    ; MessageRequester Error = #MB_ICONHAND | #MB_ICONSTOP | #MB_ICONERROR
  MessageRequester(PB_CP, txt, #MB_ICONERROR)
EndMacro
ImportC ""
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    _wcslen_(*String) As "wcslen"
    _wcsstr_(*String1, *String2) As "wcsstr"
  CompilerElse
    _wcslen_(*String) As "_wcslen"
    _wcsstr_(*String1, *String2) As "_wcsstr"
  CompilerEndIf
EndImport
Procedure.i SplitC(*String.Character, Array A$(1), *Delimiter)
  ;nco2k, http://www.purebasic.fr/english/viewtopic.php?p=516082#p516082
  ;skywalk; modified to catch trailing null's.
  ; Ex. "1,2,3,," Splits with ',' -> [1][2][3][][].
  Protected.i *StringEnd, DelimiterLength, ArrayIndex
  Protected.i Resize = 511
  Protected.i nStrings = ArraySize(A$())
  If *String    ; Avoid 'Pointer is null' if pointing to an array element = Empty$
    If *String\c
      DelimiterLength = _wcslen_(*Delimiter) * SizeOf(Character)
      If DelimiterLength
        Repeat
          *StringEnd = _wcsstr_(*String, *Delimiter)
          If *StringEnd
            A$(ArrayIndex) = PeekS(*String, (*StringEnd - *String) / SizeOf(Character))
            ArrayIndex + 1
            If ArrayIndex > nStrings
              nStrings + Resize
              ReDim A$(nStrings)
            EndIf
            *String = *StringEnd + DelimiterLength
          Else
            Break
          EndIf
        ForEver
      EndIf
      ReDim A$(ArrayIndex)
      A$(ArrayIndex) = PeekS(*String)   ; Catch final trailing null's if any.
      ArrayIndex + 1
    EndIf
  EndIf
  ProcedureReturn ArrayIndex
EndProcedure
Procedure.i SF_HasBadChar(s$)
  ; Verify that string does not contain illegal characters, since it will be used for a filename.
  ; such as: /, \, :, *, ?, ", <, >, |    ; Windows 10
  Protected Dim A$(10)
  Protected.i i, ri
  A$(0) = #PS$  ;"\"
  A$(1) = #NPS$ ;"/"
  A$(2) = ":"
  A$(3) = "*"
  A$(4) = "?"
  A$(5) = #DQUOTE$
  A$(6) = "<"
  A$(7) = ">"
  A$(8) = "|"
  For i = 0 To 8
    If FindString(s$, A$(i))
      ri = 1
      Break
    EndIf
  Next i
  ProcedureReturn ri
EndProcedure
Procedure.i FL_CreateFullDirPath(DirPath$)
  ; REV:  100405, skywalk
  ; REV:  180325, skywalk
  ;       Bug in FileSize() for existing path queried with a bad char?
  ;       Allows wildcards in its search: ?,*, including '<','>'.
  ; No recursion.
  ; Windows rejects certain characters within pathname:
  ;   / \ : * ? " < > |
  Protected.i i, k, ri
  CompilerIf 0
    ; Check if path exists?
    If FL_FileExists(DirPath$) = -1
      ProcedureReturn 1
    Else
      ri = CreateDirectory(DirPath$)
      If FL_FileExists(DirPath$) = -1
        ProcedureReturn 1
      EndIf
    EndIf
  CompilerEndIf
  Protected.s TestPath$
  Protected Dim tmppath$(0)
  k = SplitC(@DirPath$, tmppath$(), @OS_PATH_SEP$) ;BUG; PB v573 does not support @#OS_PATH_SEP$
  If k > 1
    TestPath$ = tmppath$(0)
    i = 1   ; Do not allow creation of 1st dir entry, "c:\"
    Repeat
      If SF_HasBadChar(tmppath$(i)) = 0
        TestPath$ = TestPath$ + OS_PATH_SEP$ + tmppath$(i)
        ri = CreateDirectory(TestPath$)
        Delay(5)
        If (ri = 0) And (i = k)
          i = 0
          MRE("Error creating dir structure:" + #CRLF$ + DirPath$ + #CRLF$ + "Verify Write access to drive.")
          Break
        EndIf
        i + 1
      Else
        i = 0
        MRE("Error creating dir structure:" + #CRLF$ + DirPath$ + #CRLF$ + "May contain invalid character.")
        Break
      EndIf
    Until i = k
    ProcedureReturn i
  Else
    ProcedureReturn i
  EndIf
EndProcedure
Debug FL_CreateFullDirPath("c:\try3\z1\z2\z3\z4\z5")
Debug FL_CreateFullDirPath("c:/try3/z1/z2/z3/z4/")
Debug FL_CreateFullDirPath("c:\try3\z\zz\|txt")
;FL_CreateFullDirPath("c:\try3\z\z*z\")
;FL_CreateFullDirPath("c:\try2\try 3\try 4\")

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 1:29 am
by BarryG

Code: Select all

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  Global.s OS_PATH_SEP$ = #PS$
CompilerElse
  Global.s OS_PATH_SEP$ = #NPS$
CompilerEndIf
I thought #PS$ was supposed to hold the correct path separator (backslash or forwardslash) depending on the OS being compiled for? Why CompilerIf here?

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 2:30 am
by skywalk
Hmmm, I needed a non constant string variable for @path$. @#PS$ is not allowed.

I don't think the contents of #PS$ change per OS, else there would only be 1 constant. No?

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 2:46 am
by Demivec
skywalk wrote:Hmmm, I needed a non constant string variable for @path$. @#PS$ is not allowed.

I don't think the contents of #PS$ change per OS, else there would only be 1 constant. No?
Constants like #PB_Compiler_#PB_Compiler_Debugger change so why not one that changes with the OS used?

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 2:52 am
by skywalk
Just a hunch, cause there are not 2 #debugger constants like #PS and #NPS.
Why is there no #PB_OS_PATH_SEP$?

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 4:00 am
by Demivec
skywalk wrote:Just a hunch, cause there are not 2 #debugger constants like #PS and #NPS.
Why is there no #PB_OS_PATH_SEP$?
I agree the name is a little vague. I'm guessing it was to keep it short and as terse as possible, similar to the #LF$, #CR$, #CRLF$ constants.

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 4:02 am
by BarryG
skywalk wrote:I don't think the contents of #PS$ change per OS, else there would only be 1 constant. No?
No. That's why #PS$ was introduced, to work on all OSes. It's in the Help:

Code: Select all

Added: #PS, #NPS, #PS$ and #NPS$ constants (Path seperator character depending of the OS)
skywalk wrote:Why is there no #PB_OS_PATH_SEP$?
There is - just what I said above.

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 5:06 am
by skywalk
Dude? You are not explaining why there is #PS$ and #NPS$????
If the compiler changes the value per OS, why the 2 constants?

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 5:49 am
by collectordave
#PS$ does change depending on the OS.

I can only assume that #NPS$ is NOT #PS$.

Debugged both on the MAC

Code: Select all

Debug #PS$
Debug #NPS$
and I get

/
\

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 5:54 am
by Demivec
A quote from viewtopic.php?f=13&t=72340&p=533252&hil ... er#p533252
NicTheQuick wrote:Consider the following code:

Code: Select all

Debug #PS
Debug #NPS
Debug #PS$
Debug #NPS$
On Linux the result is:

Code: Select all

47
92
/
\
On Windows the result is:

Code: Select all

92
47
\
/

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 5:57 am
by skywalk
Cool, thanks for confirming. Bummer I still need the global string variable for the byref parameter.

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 6:39 am
by BarryG
skywalk wrote:Dude? You are not explaining why there is #PS$ and #NPS$????
If the compiler changes the value per OS, why the 2 constants?
I didn't write the manual, so I don't know. All I know is that #PS$ stands for path separator, but I don't know what the N in #NPS$ would mean. The manual doesn't say (as I quoted it).

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 10:16 am
by NicTheQuick
skywalk wrote:This is what I use, and it is not recursive.

Code: Select all

...
The procedure "SF_HasBadChar" is wrong on Linux. On Linux the only character which is not allowed for file names is the forward slash or path separator.

Re: CreateDirectory() recursively or CreatePath()

Posted: Fri Jan 08, 2021 4:01 pm
by skywalk
Yes, that makes sense. I am merely trying to maintain compatibility with Windows transfers between Linux servers.