No announcement yet.

Convert relative path to abolute path?

  • Filter
  • Time
  • Show
Clear All
new posts

  • Convert relative path to abolute path?

    I have been working on a project for a client in which the configuration file is is to support a series of "folder names" to direct certain outputs.

    I would like to support relative paths such as ...

    .\data\smith << would be same as 'data\smith'
    ..\data\smith << would not be the same.

    I was working with a number of WinAPI and intrinsic PB functions yesterday and could not find the magic combination which would convert these relative paths to fully-qualified absolute paths... eg
    If currrent directory is "d:\RB835" then

    .\data\smith ==> d:\RB835\data\smith

    ..\data\smith ==> D:\data\smith

    Does anyone have any good ideas for converting these "dot" and "dot-dot" entries from the relative form to the absolute form?

    I also want to support entry of absolute paths; but I think I can just identify these as those starting with either "x:\" [fully qualified] or just "\" [current drive assumed]

    OOPS forgot....

    The named path may or may not exist at the time it is checked... at which time I have to create it.

    ShCreateDirectory() works great (handles any 'missing' subdirectories automatically) , but that requires a fully-qualified path, which is why I am trying to get the absolute path name.

    Last edited by Michael Mattias; 9 Jun 2009, 08:40 AM.
    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]

  • #2
    Here's as couple of functions I use once I have a fully-qualified file or folder name. Maybe these will give someone an idea to solve my direct problem....

    IsValidFolder requires the folder exist (and works with relative folders)
    IsValidOutfileName does not.

    FUNCTION IsValidFolder (szPath AS ASCIIZ) AS LONG
      FA         = GetFileAttributes(szPath)
      'MSGBOX "FA=" & HEX$(FA,8) & $CRLF & szPath
      IF FA = -1& THEN
          FUNCTION = 0
      END IF
    ' FIXED. A Wildcard here is automatically an invalid output file name
        ' see if a file name is valid by trying to open it
        ' returns true if we can create the file...or if it already exists else false
        LOCAL hFile AS LONG, E AS LONG, fs AS LONG
        LOCAL iPos AS LONG
        iPos = INSTR (szFN, ANY "?*")
        IF ISTRUE iPos THEN
            FUNCTION = %FALSE
            EXIT FUNCTION
        END IF
        IF DIR$(szFn) <> "" THEN  ' file exists, so the name must be valid
            FUNCTION  = -1&
            EXIT FUNCTION
        END IF
        hFile = FREEFILE
        E = ERRCLEAR
        'MSGBOX "E on open of " & szfn & " =" & STR$(E)
            fs = LOF(hFile)
            CLOSE hFile
            IF fs = 0 THEN   ' we just created it...empty..
               KILL szFN
            END IF
        END IF
        FUNCTION = (E=0)
    Last edited by Michael Mattias; 9 Jun 2009, 08:47 AM.
    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]


    • #3 shows there is a Python function for that. So maybe studying the Python Win32 extensions source code would give a clue.
      Erich Schulman (KT4VOL/KTN4CA)
      Go Big Orange


      • #4
        LOCAL dwLen AS DWORD
        LOCAL szBuffer AS ASCIIZ * %MAX_PATH
        dwLen = GetFullPathName(".\data\smith", %MAX_PATH, szBuffer, BYVAL %NULL)


        • #5
          Are you looking for something like this?

          Function ReturnFullPath(ByVal PathStr As String, Optional ByVal UseProgramDirectory As Dword) As String
             Local StartDir  As String
             Local WorkDrive As String
             Local PthSegmnt As String
             Local sWork     As String
             Local idx       As Dword
             Local idx2      As Dword
             If UseProgramDirectory Then
                StartDir = EXE.Path$
                StartDir = CurDir$
             End If
             StartDir = RTrim$(StartDir, "\") ' remove any trailing backslashes
             If Mid$(PathStr,2,2) = ":\" Then
                StartDir = PathStr
                StartDir = RTrim$(StartDir, "\")
                WorkDrive = Left$(StartDir, 3)
                PathStr = Mid$(StartDir,4)
                StartDir = ""
                WorkDrive = Left$(StartDir, 3)
                StartDir = Mid$(StartDir, 4)
             End If
             For idx = 1 To ParseCount(PathStr, "\")
                PthSegmnt = Parse$(PathStr, "\", idx)
                If PthSegmnt = ".." Then ' Back one
                   If Len(StartDir) Then
                      sWork = ""
                      For idx2 = 1 To ParseCount(StartDir, "\") - 1
                         sWork &= "\" & Parse$(StartDir, "\", idx2)
                      Next idx2
                      StartDir = Trim$(sWork, "\")
                   End If
                ElseIf idx =1 And PthSegmnt = "" Then
                   StartDir = ""
                ElseIf (PthSegmnt <> ".") And (PthSegmnt <> "") Then
                   StartDir &= "\" & PthSegmnt
                   StartDir = Trim$(StartDir, "\")
                End If
             Next idx
             Function = WorkDrive & StartDir
          End Function
          Last edited by Scott Slater; 9 Jun 2009, 10:30 AM.
          Scott Slater
          Summit Computer Networks, Inc.


          • #6
            Thanks for the tips, they got me where I needed to be.

            You are going to love what my problem was....

            I was trying to make this work using GetLongPathname instead of GetFullPathName.

            I can now attest from personal experience they are in fact two different functions and they do not work the same way.

            Michael Mattias
            Tal Systems Inc. (retired)
            Racine WI USA
            [email protected]


            • #7
              Path functions are already provided by Windows and defined in SHLWAPI.INC > PathXX functions (particularly PathRelativePathTo)
     | Slam DBMS | PrpT Control | Other Downloads | Contact Me


              • #8
                >Path functions are already provided by Windows

                Duh, how about this one...

                PathResolve Function


                Converts a relative or unqualified path name to a fully-qualified path name.
                Sounds pretty close to what I wanted, huh?
                Michael Mattias
                Tal Systems Inc. (retired)
                Racine WI USA
                [email protected]


                • #9
                  This do what you need?

                  #INCLUDE ""
                  FUNCTION RealPath( strSource AS STRING ) AS STRING
                   LOCAL strTargetEES AS STRING
                   LOCAL strTargetGFMN AS STRING
                   LOCAL lngReturnedLen AS LONG
                   LOCAL strBuffer AS STRING
                   LOCAL pFilePart AS DWORD
                   ' Expand any environment strings first
                   strTargetEES = SPACE$( %MAX_PATH + 1 )
                   lngReturnedLen = EXPANDENVIRONMENTSTRINGS( BYCOPY strSource, BYVAL STRPTR( strTargetEES ), LEN( strTargetEES ))
                   ' did EES work?
                   IF lngReturnedLen THEN
                    ' Expand to a full path
                    strTargetEES = LEFT$( strTargetEES, lngReturnedLen - 1 )
                    strBuffer = SPACE$( %MAX_PATH + 1 )
                    lngReturnedLen = GETFULLPATHNAME( BYCOPY strTargetEES, LEN( strBuffer ), BYVAL STRPTR( strBuffer ), pFilePart )
                    ' did GFPN work?
                    IF lngReturnedLen THEN
                     FUNCTION = LEFT$( strBuffer, lngReturnedLen )
                     FUNCTION = "Error on GFPN"
                    END IF
                    FUNCTION = "Error on EES"
                   END IF
                  END FUNCTION
                  FUNCTION PBMAIN( )
                   MSGBOX RealPath( "%TEMP%" )
                   MSGBOX RealPath( "%TEMP%\.." )
                   MSGBOX RealPath( "%TEMP%\.." )
                  END FUNCTION
                  BTW, an important threading note about GetFullPathName from the MSDN docs (

                  Multi-threaded applications and shared library code should should not use the GetFullPathName function. The current directory state written by the SetCurrentDirectory function is stored as a global variable in each process, therefore multi-threaded applications cannot reliably use this value without possible data corruption from other threads that may also be reading or setting this value. This limitation also applies to the SetCurrentDirectory and GetCurrentDirectory functions.
                  Last edited by George Bleck; 9 Jun 2009, 01:20 PM.
                  <b>George W. Bleck</b>
                  <img src=''>


                  • #10
                    Here is what I did...
                    ' NEW FUNCTION VERSION 2.1
                    ' Returns: FALSE = NO ERRORS
                    ' TRUE = one or more errors
                    FUNCTION EditCustPath (szInFileNameExt AS ASCIIZ, cfg() AS CONFIGFileType) AS LONG
                    ' for any config file entry with a custPath column, make that column the new file name
                    ' which is the path specified in the cfg.szPath + szInfileNameExt
                    ' and make sure I can write it.
                    ' How do I allow for relative paths, which I want to convert to absolute full paths?
                    ' GetLongPathName? that just might do it IT DOES NOT BUT Get**FULL**Pathname works good
                    ' I think I will call this with some prompts as a test program.
                     LOCAL sz AS ASCIIZ * %MAX_PATH
                     LOCAL szFullPath AS ASCIIZ * %MAX_PATH
                     LOCAL dwAddr     AS DWORD
                     LOCAL iRET AS LONG
                     LOCAL iVF  AS LONG
                     LOCAL swChar   AS STRING
                     LOCAL LE  AS LONG
                     LOCAL iCfg AS LONG
                     ' GETFULLPATHNAME works perfectly even with multiple nodes!!!
                     ' See also PathResolve()
                     LOCAL bErr AS LONG  ' set to true as soon as any error occurs
                     FOR iCfg = LBOUND(cfg,1) TO UBOUND (cfg,1)
                          sz  = Cfg(icfg).szPath    ' what was loaded from config file
                          STDOUT USING$ ("Checking config File entry # _, Path is '&'", iCfg +1&, sz)
                          IF LStrLen(sz)  THEN      ' if one was found
                            ' get the fully-qualified name, we need that for multiple purposes
                          ' Is it a valid folder?
                            RESET    szFullPath
                            iRet =   GetFullpathName ( sz, SIZEOF(szFullPath), szFullPath, dwAddr)  ' returns TRUE on success
                            LE = getLastError
                            IF ISTRUE iREt THEN    ' we got the full name back
                              iRet = %ERROR_SUCCESS  ' what we use later
                              STDOUT USING$ ("  Fully Qualified Path is '&'", szFullPath)
                              ' is this an existing valid folder?
                              ivf  =  IsValidFolder (szFullPath)
                              IF ISTRUE ivf THEN
                                   STDOUT "   This is an existing folder"
                                   STDOUT "   Folder not found; will attempt to create it."
                                   swChar =  UCODE$(szFullPath) & CHR$(0,0)   ' make sure it's Unicode terminated
                                   iRet    = ShCreateDirectory (GetDesktopWindow(), BYVAL STRPTR(swChar))  ' returns 0 ERROR_SUCCESS
                                   IF iRet = %ERROR_SUCCESS THEN
                                        STDOUT "   Folder successfully created"
                                        STDOUT  USING$("   Could not create folder '&'", szFullPath)
                                        STDOUT         "   See STDERR for details"
                                        STDERR2 USING$("   Error message is &", SystemErrorMessageText(iRet))
                                        bErr        =  %TRUE
                                   END IF
                              END IF
                                 STDOUT USING$("   Could not get full-qualified path name for '&'", sz)
                                 STDOUT USING$("   Error message is &", SystemErrorMEssageText(LE))
                                 bERR        = %TRUE
                            END IF
                            IF ISFALSE Iret THEN  ' everyting was OK
                                 ' make the cfg entry = path + Input file name
                                 cfg(iCfg).szpath =  szFullPath & "\" & szInFileNameExt
                                 STDOUT USING$ ("   Set Customer file name to '&'", cfg(iCfg).szPath)
                            END IF
                        END IF ' if customer even had a path entry in the config file
                     NEXT iCfg
                     ' ** LOGIcAL END OF FUNCTION **
                     FUNCTION = bErr
                    #IF 0
                       THIS IS TEST CODE ONLY             ' change cfg entry to be input file
                           STDOUT USING$ ("CURDIR$==>'&'", CURDIR$)   ' does not return trailing slash
                           LINE INPUT "Enter cust Path to convert", sz
                           IF LEN (sz) THEN
                                RESET  szFullPath
                                IF ISFALSE IVF THEN
                                     s = sz
                                     STDOUT USING$("Pathnames for path &", PATHNAME$(PATH, s))
                                     STDOUT USING$ ("   Creating folder '&'", s)
                                    ' sWChar =  UCODE$(s) & CHR$(0,0)
                                     ' this needs fully-qualified path
                                     MKDIR  s   ' fails with multiple nodes.Ok wioth A\DAta as long as A exists.
                                     'STDOUT "Create Folder Returns " & SystemErrorMEssageText(iret)
                                END IF
                                EXIT FUNCTION
                           END IF
                    END FUNCTION
                    Probably more than you wanted to know, but hey, what the heck.

                    Michael Mattias
                    Tal Systems Inc. (retired)
                    Racine WI USA
                    [email protected]