Skip to content

Split-Path works with uri, but Join-Path does not #20011

@dkaszews

Description

@dkaszews

Prerequisites

Steps to reproduce

Join-Path fails on uris and Windows-style absolute paths when on Linux (I suspect it also fails with Unix-style absolute paths on Windows, but don't have a machine to confirm). This is different to Resolve-Path failing on non-existant files (see #2993), as those work just fine. It is also inconsistent with Split-Path, which does not care about anything.

I discovered it when trying to use Join-Path to form uri for Invoke-RestMethod, as ${Parent}/${Leaf} would sometimes fail due to trailing /.

It is best demonstrated with the following test function:

function Test-RejoinPath($Path) {
    Split-Path -Parent $Path | Tee-Object -Variable Parent
    Split-Path -Leaf $Path | Tee-Object -Variable Leaf
    Join-Path $Parent $Leaf
}

Expected behavior

> test-RejoinPath '/home/me/file.txt'
/home/me
file.txt
/home/me/file.txt

> Test-RejoinPath 'C:/Users/me/file.txt'  # On Linux
C:/Users/me
file.txt
C:/Users/me/file.txt

> Test-RejoinPath 'example.com/file.txt'
example.com
file.txt
example.com/file.txt

> Test-RejoinPath 'https://example.com/file.txt'
https://example.com
file.txt
https://example.com/file.txt

Actual behavior

> test-RejoinPath '/home/me/file.txt'
/home/me
file.txt
/home/me/file.txt

> Test-RejoinPath 'C:/Users/me/file.txt'  # On Linux
C:/Users/me
file.txt
Join-Path:
Line |
   4 |      Join-Path $Parent $Leaf
     |      ~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot find drive. A drive with the name 'C' does not exist.

> Test-RejoinPath 'example.com/file.txt'
example.com
file.txt
example.com/file.txt

> Test-RejoinPath 'https://example.com/file.txt'
https://example.com
file.txt
Join-Path:
Line |
   4 |      Join-Path $Parent $Leaf
     |      ~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot find drive. A drive with the name 'https' does not exist.

Error details

Exception             :
    Type                 : System.Management.Automation.DriveNotFoundException
    ErrorRecord          :
        Exception             :
            Type    : System.Management.Automation.ParentContainsErrorRecordException
            Message : Cannot find drive. A drive with the name 'https' does not exist.
            HResult : -2146233087
        TargetObject          : https
        CategoryInfo          : ObjectNotFound: (https:String) [], ParentContainsErrorRecordException
        FullyQualifiedErrorId : DriveNotFound
    ItemName             : https
    SessionStateCategory : Drive
    TargetSite           :
        Name          : GetDrive
        DeclaringType : System.Management.Automation.SessionStateInternal, System.Management.Automation,
Version=7.4.0.4, Culture=neutral, PublicKeyToken=31bf3856ad364e35
        MemberType    : Method
        Module        : System.Management.Automation.dll
    Message              : Cannot find drive. A drive with the name 'https' does not exist.
    Source               : System.Management.Automation
    HResult              : -2146233087
    StackTrace           :
   at System.Management.Automation.SessionStateInternal.GetDrive(String name, Boolean automount)
   at System.Management.Automation.SessionStateInternal.GetDrive(String name, Boolean automount)
   at System.Management.Automation.LocationGlobber.GetDriveRootRelativePathFromPSPath(String path,
CmdletProviderContext context, Boolean escapeCurrentLocation, PSDriveInfo& workingDriveForPath, CmdletProvider&
providerInstance)
   at System.Management.Automation.LocationGlobber.GetProviderPath(String path, CmdletProviderContext context,
Boolean isTrusted, ProviderInfo& provider, PSDriveInfo& drive)
   at System.Management.Automation.SessionStateInternal.MakePath(String parent, String child,
CmdletProviderContext context)
   at Microsoft.PowerShell.Commands.JoinPathCommand.ProcessRecord()
TargetObject          : https
CategoryInfo          : ObjectNotFound: (https:String) [Join-Path], DriveNotFoundException
FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.JoinPathCommand
InvocationInfo        :
    MyCommand        : Join-Path
    ScriptLineNumber : 4
    OffsetInLine     : 5
    HistoryId        : 276
    Line             : Join-Path $Parent $Leaf

    Statement        : Join-Path $Parent $Leaf
    PositionMessage  : At line:4 char:5
                       +     Join-Path $Parent $Leaf
                       +     ~~~~~~~~~~~~~~~~~~~~~~~
    InvocationName   : Join-Path
    CommandOrigin    : Internal
ScriptStackTrace      : at Test-RejoinPath, <No file>: line 4
                        at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo :

Environment data

Name                           Value
----                           -----
PSVersion                      7.4.0-preview.4
PSEdition                      Core
GitCommitId                    7.4.0-preview.4
OS                             Ubuntu 22.04.2 LTS
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Up-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributorsWG-Cmdletsgeneral cmdlet issuesWG-ReviewedA Working Group has reviewed this and made a recommendation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions