Search code examples
powershellescapingglobget-childitem

Why does Get-ChildItem -name return none if there is an escape character?


I am searching for all files containing (1) in the name. Both these commands work:

ls -r *1* -name
ls -r *1`)* 

But this doesn't:

ls -r *1`)* -name

Do you know why is that? I'm not sure if I miss something in the Get-ChildItem doc


Solution

  • The way to work around your problem is actually the conceptually simpler solution to begin with: quote your wildcard pattern (as a whole - if that doesn't help, see the next section):

    ls -r '*1)*' -name # short for: Get-ChildItem -Recurse -Path '*1)*' -Name 
    

    Note that, unlike in POSIX-compatible shells such as Bash, in PowerShell it is perfectly fine to pass wildcard patterns as single- or double-quoted strings:

    • Such patterns are not handled by PowerShell itself (the way the are in Bash, for instance), but by the target command (if supported). Therefore, the syntactic form used to pass them is incidental (unlike in Bash, for instance, where wildcard (globbing) patterns need to be unquoted in order to be treated as such).

    • As such, arguments *.txt, '*.txt' and "*.txt" are equivalent in PowerShell, and are all seen as verbatim *.txt by the target command, which must then itself perform wildcard-pattern matching, as appropriate.

    • While in POSIX-compatible shells such as Bash wildcard patterns are limited to matching files and directories based on unquoted patterns, PowerShell's wildcard support - at least in the built-in cmdlets - is generalized and therefore more versatile:

      • Many parameters of built-in cmdlets support wildcard patterns even in non-file-system contexts.

      • For instance, Select-Object's -Property parameter allows matching property names by wildcard patterns, so that in the following example -Property *Time selects the .CreationTime, .LastAccessTime and .LastWritTime properties of the [System.IO.DirectoryInfo] object output by Get-Item:

        Get-Item $PSHOME | Select-Object -Property *Time
        

    As for what you tried:

    • What you tried - metacharacter-individual escaping with ` (the so-called backtick, PowerShell's escape character) - should work.

    • *1`)* should be the same as '*1)*', i.e. a string with verbatim content *1)*, and its parsing is handled by PowerShell's parameter binder, before the target command sees it, so whether or not you also specify -Name shouldn't make a difference.

    • If there is indeed a problem:

      • Windows PowerShell, the legacy, Windows-only, ships-with-Windows edition whose latest and last version is v5.1.x, is in maintenance-only mode and only serious bugs have a chance of getting addressed - and this one probably doesn't qualify.

      • By contrast, its modern successor, the cross-platform, install-on-demand PowerShell (Core) edition is actively maintained, so if you have a reproducible case using the latest stable version or one that is still officially maintained, I encourage you to report an issue in the GitHub repo.