Skip to content

about_Case-Sensitivity lacks detail in a lot of areas #12624

@surfingoldelephant

Description

@surfingoldelephant

Prerequisites

  • Existing Issue: Search the existing issues for this repository. If there is an issue that fits your needs do not file a new one. Subscribe, react, or comment on that issue instead.
  • Descriptive Title: Write the title for this issue as a short synopsis. If possible, provide context. For example, "Typo in Get-Foo cmdlet" instead of "Typo."
  • Verify Version: If there is a mismatch between documentation and the behavior on your system, ensure that the version you are using is the same as the documentation. Check this box if they match or the issue you are reporting is not version specific.

Links

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_case-sensitivity

Summary

about_Case-Sensitivity lacks detail in a lot of areas.

The purpose of this issue is to document areas of PowerShell which are case-sensitive by default or handle case inconsistently/conditionally.

Details

Areas of PowerShell which are either case-sensitive by default or handle case inconsistently/conditionally:

  • PS providers:
    • EDIT: The FileSystem and Environment providers are case-sensitive on case-sensitive file systems non-Windows systems. Generally, operations involving paths or environment variables are case-sensitive on such systems.
    • However, wildcard matching by provider cmdlets is case-insensitive, irrespective of the system.
      [void] (New-Item -Path Temp:foo.txt -Force)
      
      (Get-Item -Path Temp:FOO.txt).Name
      # Get-Item: Cannot find path 'Temp:/FOO.txt' because it does not exist.
      
      (Get-Item -Path Temp:F[O]*.txt).Name 
      # foo.txt
      
      (Get-Item -Path Env:hOME).Name
      # Get-Item: Cannot find path 'Env:/hOME' because it does not exist.
      
      (Get-Item -Path Env:hOM[E]).Name
      # HOME
  • Parameter set names:
  • .NET methods often exhibit case-sensitive behavior by default. E.g.,
    • Equivalent .NET methods (without explicit opt-in) for common PowerShell operators.
      • E.g., Array.Contains(), String.Contains(), String.Replace(), Regex.Match(), Regex.Replace(), etc.
    • Reflection (member names must use the correct case).
    • Non-literal dictionary instantiation.
      • E.g., [hashtable]::new() has case-sensitive keys, whereas a hash table literal @{} has case-insensitive keys. Likewise with [ordered] @{} vs [ordered]::new() ([ordered] is only a type accelerator in PS v7+).
    • Explicitly calling Enum.Parse() is case-sensitive by default, whereas PowerShell typically handles enums in a case-insensitive manner.
  • -Unique cmdlets:
  • Compare-Object:
  • ConvertFrom-Json -AsHashtable:
  • Group-Object:
    • Case-insensitive by default, but does have a -CaseSensitive switch.
      • In Windows PowerShell v5.1, -CaseSensitive and -AsHashtable produces a case-insensitive hash table. Duplicate keys result in an error.
      • In PowerShell v7+, -CaseSensitive and -AsHashtable produces a case-sensitive hash table. No error occurs with duplicate keys.
      • Group-Object - Use Case-Sensitive Hashtable for -CaseSensitive -AsHashtable PowerShell/PowerShell#11030
        [pscustomobject] @{ Foo = 'Bar' }, [pscustomobject] @{ Foo = 'bar' } |
            Group-Object -Property Foo -CaseSensitive -AsHashtable
        # Win PS: The objects grouped by this property cannot be expanded because there is a key duplication.
        # PS 7+:  OK.
  • Select-String:
  • Get-Command and command discovery/invocation:
    • On case-sensitive file systems, ExternalScript and Application command type discovery/invocation is case-sensitive.
    • Get-Command wildcard matching with these types is also case-sensitive.
    • All other CommandTypes are case-insensitive (functions, cmdlets, etc).
  • Comparison operators:
    • By default, operators are case-insensitive.
    • -c* operators are case-sensitive.
    • -i* operators are case-insensitive.
    • -replace/-ireplace is case-insensitive by default, except with named capture groups, which are case-sensitive.
      'Bar' -replace '(?<a>a)', '${a}${a}'
      # Baar
      
      'Bar' -replace '(?<a>a)', '${A}${A}'
      # B${A}${A}r
  • -split operator:
    • -split and -isplit are case-insensitive.
    • -csplit is case-sensitive, unless the IgnoreCase option is specified.
      'Bar' -csplit 'A', 0
      # Bar
      
      'Bar' -csplit 'A', 0, 'IgnoreCase'
      # B
      # r
  • Tab completion:
  • using statement:
    • On case-sensitive file systems, using module and using assembly are case-sensitive when a path is specified.
    • using module with just a module name is case-insensitive.
    • using namespace is always case-insensitive.
  • Special characters:
    • Escape sequences like `n are case-sensitive.

Areas of PowerShell which are guaranteed to be case-insensitive on all systems:

  • Non-dictionary member-access
  • Operator names
  • Non-ExternalScript/Application command discovery
  • Parameter names
  • Variable names/Get-Variable/Variable:
  • Keywords
  • using namespace statements
  • Type literals
  • #Requires
  • Comment-based help
  • PS provider names
  • PS drive names
  • Scope modifiers

Suggested Fix

  • Be explicitly clear that on systems with a case-sensitive file system, the FileSystem and Environment PS providers are case-sensitive, except with wildcard matching/globbing.
  • Call out areas of PowerShell which are either case-sensitive by default on all systems or are inconsistent/conditional with case handling. See details above.
  • Add additional examples in which case-insensitivity is guaranteed on all systems.
  • Perhaps document exactly how case-sensitivity is handled in all of the main serialization/deserialization formats (CSV, JSON, XML, CLIXML) and potential workarounds with problematic input.

Metadata

Metadata

Assignees

Labels

area-aboutArea - About_ topicsissue-doc-bugIssue - error in documentation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions