Edit

Share via


about_Case-Sensitivity

Short description

PowerShell is as case-insensitive as possible while preserving case.

Long description

As a general principle, PowerShell is case-insensitive wherever possible while preserving case and not breaking the underlying OS.

Windows-based systems are case-insensitive for most operations. However, non-Windows systems are case-sensitive for most operations, especially for file system and environment variable access.

PowerShell is guaranteed to be case-insensitive on all systems for the following areas:

  • Variable names
  • Operator names
  • Non-dictionary member-access
  • Command discovery of PowerShell commands and aliases. This excludes ExternalScript and Application commands.
  • Parameter names and aliases
  • PowerShell language keywords
  • using namespace statements
  • Type literals
  • #Requires statements
  • Comment-based help keywords
  • PSProvider names
  • PSDrive names
  • Scope modifiers

Special cases

  • Module names are case-insensitive (with exceptions)

    The name of the module is purely a PowerShell concept and treated case-insensitively. However, there is a strong mapping to a foldername, which can be case-sensitive in the underlying operating system. Importing two modules with the same case-insensitive name has the same behavior as importing two modules with the same name from different paths.

    The name of a module is stored in the session state using the case by which it was imported. The name, as stored in the session state, is used by Update-Help when looking for new help files. The web service that serves the help files for Microsoft uses a case-sensitive file system. When the case of the imported name of the module doesn't match, Update-Help can't find the help files and reports an error.

  • PS providers:

    The FileSystem and Environment providers are case-sensitive on 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.

    PS /home/user01> New-Item -Path Temp:foo.txt -Force
    
        Directory: /tmp
    
    UnixMode      User Group      LastWriteTime         Size Name
    --------      ---- -----      -------------         ---- ----
    -rw-r--r--  user01 user01    1/6/2026 10:53            0 foo.txt
    
    PS /home/user01> (Get-Item -Path Temp:FOO.txt).Name
    Get-Item: Cannot find path 'Temp:/FOO.txt' because it does not exist.
    
    PS /home/user01> (Get-Item -Path Temp:F[O]*.txt).Name
    foo.txt
    
    PS /home/user01> (Get-Item -Path Env:hOM[E]).Name
    HOME
    
  • Parameter set names are case-sensitive.

    The DefaultParameterSetName case must be identical to ParameterSetName.

  • .NET methods often exhibit case-sensitive behavior by default.

    Examples include:

    • Equivalent .NET methods (without explicit opt-in) for common PowerShell operators such as:
      • Array.Contains(), String.Contains(), String.Replace(), Regex.Match(), Regex.Replace()
    • Reflection; member names must use the correct case.
    • Non-literal dictionary instantiation. For example:
      • [hashtable]::new() has case-sensitive keys, whereas a hashtable literal @{} has case-insensitive keys.
      • [ordered]::new() has case-sensitive keys, whereas a [ordered] @{} has case-insensitive keys. The [ordered] type accelerator isn't available in PowerShell v5.1 and earlier.
    • Explicitly calling Enum.Parse() is case-sensitive by default, whereas PowerShell typically handles enums in a case-insensitive manner.
  • -Unique cmdlets:

  • Compare-Object is case-insensitive by default, but has a -CaseSensitive switch. Comparison of [char] types is case-sensitive by default. String comparison is case-insensitive by default.

    # Compare strings - Equal (no output)
    Compare-object -ReferenceObject a            -DifferenceObject A
    # Compare chars - Different (output)
    Compare-object -ReferenceObject ([char] 'a') -DifferenceObject ([char] 'A')
    
  • 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 hashtable. Duplicate keys result in an error.

      [pscustomobject] @{ Foo = 'Bar' }, [pscustomobject] @{ Foo = 'bar' } |
          Group-Object -Property Foo -CaseSensitive -AsHashtable
      
      Group-Object : The objects grouped by this property cannot be expanded
      because there is a key duplication. Provide a valid value for the
      property, and then try again.
      At line:2 char:11
      +           Group-Object -Property Foo -CaseSensitive -AsHashtable
      +           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : InvalidArgument: (:) [Group-Object], Exception
          + FullyQualifiedErrorId : The objects grouped by this property
      cannot be expanded because there is a key duplication. Provide a valid
      value for the property, and then try again.,Microsoft.PowerShell.Comman
      ds.GroupObjectCommand
      
    • In PowerShell v7 and higher, -CaseSensitive and -AsHashtable produces a case-sensitive hashtable. No error occurs with duplicate keys.

      [pscustomobject] @{ Foo = 'Bar' }, [pscustomobject] @{ Foo = 'bar' } |
          Group-Object -Property Foo -CaseSensitive -AsHashtable
      
      Name                           Value
      ----                           -----
      Bar                            {@{Foo=Bar}}
      bar                            {@{Foo=bar}}
      
  • Select-String:

  • Get-Command and command discovery/invocation:

    • On case-sensitive file systems, discovery and invocation of ExternalScript and Application command are case-sensitive.
    • Get-Command wildcard matching with these types is also case-sensitive.
    • All other CommandTypes are case-insensitive.
  • 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:

    • On case-sensitive file systems, tab completion and globbing are both case-insensitive. For example, TabExpansion2 -inputScript ./foo will complete to ./Foo.txt on Linux.
  • 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.

See also