Skip to content

Bug fixes needed to support interchangeable use of "/" (forward slash) and "\" (backslash) in file paths on Unix-like platforms #9244

Closed

Description

Note:


From the committee decision at #8587 (comment):

Filesystem accepting both / and \ on all systems is an explicit cross platform experience decision for PowerShell.

Given that it's currently impossible on Unix-like platforms - where \ is a legal filename character - to access or wildcard-match filenames with embedded \ chars., the following fixes are needed:

  • Wildcard matching must able to match \ chars., namely via ? or * or [\].

    • Note that inside [...], \ shouldn't require escaping, analogous to [.] matching a literal . in a regex.
  • -Path and -LiteralPath arguments must support `-escaping of \ chars. to request their literal treatment.

  • The .PS* provider property values (.PSPath, .PSParentPath, .PSChildName) must reflect the escaped path.

  • To-native-path conversions such as with Convert-Path must remove the escaping.

  • Native globbing must not break if a wildcard pattern happens to match a filename that contains \.

Note:

  • Even the above doesn't address the awkwardness of the - unescaped - .FullName value of System.IO.FileSystemInfo not being directly usable with the filesystem provider; e.g., with the provider bug fixed, something like (Get-ChildItem "$HOME/a\b").FullName would return something like /Users/jdoe/a\b - unescaped.

  • Similarly, native paths from outside sources with embedded \ - e.g., read from a file - will break in PowerShell commands, unless explicit escaping with -replace '`', '\`' is performed.

  • ` as the escape char. means that it requires doubling inside "..." and therefore also in unquoted arguments in order to be passed through; i.e., the following calls would be equivalent and match a file literally named a\b:

Get-Item 'a`\b'
Get-Item "a``\b" # !! 
Get-Item a``\b # !! implicitly treated like a "..." string
  • Handling ` instances that precede a char. other than \ gets quite tricky:

    • Literal paths: So as not to break the existing ability to match ` literally in paths, ` must be special only before \ and before ` itself. This follows the model of \ use in double-quoted strings in Bash, but introduces the awkwardness of needing to interpret 'a`b' and 'ab' `` the same (similar to how "a\b" and `"a\b"` are equal in Bash).

    • Wildcard paths: Wildcard matching itself always requires doubling of ` for literal use; e.g.,
      'a`b' -like 'a`b' is $false, and only 'a`b' -like 'a``b' is $true (edge case: 'a`' -like 'a`' is also $true - the trailing syntactically incomplete use of ` is interpreted as a literal).

      • However, use of wildcards with the filesystem provider:
        • currently makes Get-Item -Path 'a`b' match a file literally named a`b, even though it shouldn't.
        • currently doesn't find a match with Get-Item -Path 'ab' and neither with Get-Item -Path 'a?' , even though it should.
      • In other words: wildcard handling by the filesystem provider is currently broken - this may be related to Backtick escaping inconsistent #7999.
      • While falling back to literal interpretation is perhaps useful, especially given that -Path is the default parameter, this should be fixed, separately.

Steps to reproduce

On macOS or Linux, run the following Pester tests:

# Note: -Skip isn't yet supported at the level of Describe and Context blocks.
#        See https://github.com/pester/Pester/issues/442
if ($env:OS -eq 'Windows_NT') {
  Write-Warning "Tests apply to Unix-like platforms only" }
else {
  Describe "Support for backslashes in Unix filenames" {
    BeforeAll  {
      Push-Location TestDrive:\
      # File with literal backslash in its name.
      touch 'a\b'
      $nativePath = ($PWD.ProviderPath -replace '/$') + '/' + 'a\b'
      $escapedName = 'a`\b'
      $escapedPath = ((Get-Item .).PSPath -replace '/$') + '/' + $escapedName
      # File with literal backtick in its name.
      touch 'a`b'
    }
    It "Backslashes can be matched with wildcards" {
      (Get-Item -Path 'a?b').Name   | Should -BeExactly 'a\b'
      (Get-Item -Path 'a*b').Name   | Should -BeExactly 'a\b'
      (Get-Item -Path 'a[\]b').Name | Should -BeExactly 'a\b'
    }
    It "Backtick-escaped backslashes match literal ones in filenames" {
      (Get-Item -Path 'a`\b').Name | Should -BeExactly 'a\b'
      (Get-Item -LiteralPath 'a`\b').Name | Should -BeExactly 'a\b'
    }
    It "Backticks not preceding a backslash or backtick are literals in literal paths" {
      (Get-Item -LiteralPath 'a`b').Name | Should -BeExactly 'a`b'
    }
    It "Doubled backticks are also literals in literal paths" {
      (Get-Item -LiteralPath 'a``b').Name | Should -BeExactly 'a`b'
    }
    It "Backtick-escaped backticks must be recognized as a literal backtick in wildcard paths" {
      (Get-Item -Path 'a``?').Name | Should -BeExactly 'a`b'
    }
    It "Provider properties contain escaped paths" {
      (Get-Item -LiteralPath 'a`\b').PSChildName | Should -BeExactly $escapedName
      (Get-Item -LiteralPath 'a`\b').PSPath | Should -BeExactly $escapedPath
    }
    It "Convert-Path removes the PS-specific escaping" {
      Get-Item -LiteralPath 'a`\b' | Convert-Path | Should -BeExactly $nativePath
    }
    It "Native globbing doesn't break when a filename with a backslash is among the matches" {
      /bin/echo a* | Should -Not -Match '\*'
    }
    AfterAll {
      Pop-Location
    }
  }

}

Expected behavior

All tests should pass.

Actual behavior

All tests except "Backticks not preceding a backslash or backtick are literals in literal paths" fail.

Environment data

PowerShell Core 6.2.0-rc.1

Activity

  1. added
    Issue-Questionideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a
    on Mar 28, 2019
  2. SteveL-MSFT commented on Mar 29, 2019

    @SteveL-MSFT
    Member

    If we ever get around to #5785, we can decide what the default behavior should be with regards to slashes.

  3. changed the title [-]Bug fixes needed to support interchangeable use of "/" and "\" in file paths on Unix-like platforms[/-] [+]Bug fixes needed to support interchangeable use of "/" (forward slash) and "\" (backslash) in file paths on Unix-like platforms[/+] on Mar 29, 2019
  4. mklement0 commented on Mar 29, 2019

    @mklement0
    ContributorAuthor

    Steve Lee (@SteveL-MSFT), can you please clarify?

    with regards to slashes

    Did you mean backslashes?

    If we ever get around to #5785

    Does this mean that, for the time being, explicit cross platform experience translates to:

    • "You can use \ and / interchangeably on all platforms, as long as you don't expect filenames with embedded \ chars. to work on Unix-like platforms"?

    Do you feel that there are aspects of #8158 and #6833 not covered here?

    • If so which?
    • If not, can you please close them?
  5. SteveL-MSFT commented on Mar 29, 2019

    @SteveL-MSFT
    Member

    I'm using 'slashes' as a generic term for both forward and backslashes.

    Yes, current expectation is that you can use \ and / interchangeably on all platforms, except where filename/directoryname contains \.

    #6833 (comment) summarizes the PS-Committee stance.

    Unlike the square brackets, it's unclear to me how often people use the backtick ` or the backslash \ within file/directory names.

    I'm ok closing the older issues as dupes of this one (although it's a bit backwards...) as I believe this does summarize the issues.

  6. mklement0 commented on Mar 29, 2019

    @mklement0
    ContributorAuthor

    Thanks, Steve Lee (@SteveL-MSFT).

    Good point that use of ` and \ in filenames may be rare, but it's still problematic to make native capabilities inaccessible (currently) and providing a workaround is both a nontrivial implementation effort and a pitfall for and burden on those who do wish to use \.

    I'm ok closing the older issues as dupes of this one (although it's a bit backwards...

    I don't think that's problematic, as long as the later issue properly references and summarizes the earlier one(s), and the benefit is that future readers are spared the need to cull information from lengthy exchanges and potential confusion over what the way forward is.

  7. added
    Issue-BugIssue has been identified as a bug in the product
    WG-Engine-Providersbuilt-in PowerShell providers such as FileSystem, Certificates, Registry, etc.
    and removed
    Issue-Questionideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a
    on Mar 30, 2019
  8. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  9. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  10. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  11. microsoft-github-policy-service commented on Nov 23, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-FileSystem-Providerspecific to the FileSystem providerIssue-BugIssue has been identified as a bug in the productResolution-No ActivityIssue has had no activity for 6 months or moreWG-Engine-Providersbuilt-in PowerShell providers such as FileSystem, Certificates, Registry, etc.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions