Skip to content

Document switch -File in more detail #11810

@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_switch

Summary

Documentation on switch -File currently consists of a brief, two line description. In general, its an underutilized feature despite having advantages over common alternatives, which may in part be caused by a lack of promotion in documentation.

The documentation is currently missing:

  • Details on its efficient line-by-line streaming behavior.
  • An explanation as to why it might be preferable to Get-Content when processing a large file line-by-line.
  • Caveats with its filename argument to be aware of.
  • An example.

The current "Each line of the file is read" statement is also misleading, as it implies the entire file is read into memory.

Details

  • At no point is the entire file read into memory. It's streamed line-by-line, so breaking after matching the first line will return almost immediately.

  • Get-Content, by default, decorates each emitted string with ETS members, which is largely responsible for its well-known slowness. switch -File does not and thus performs considerably better (especially with large files).

  • switch -File combined with -Wildcard or -Regex makes it a performant and convenient/flexible option for pattern matching line-by-line.

    switch -Wildcard -File path\to\file {
        *foo* { break }        # Short-circuit as soon as *foo* matches 
        *bar* { $_; continue } # Emit the current line to the pipeline if *bar* matches
        # ...
    }

Caveats:

  • Its filename argument only supports a single file.

  • filename is invariably interpreted as a wildcard expression. If wildcard matching isn't desired, the path must be manually escaped. See this issue for details.

    $file = (New-Item -Path 'Temp:\Foo[0]' -Value Foo -Force).FullName
    switch -File $file { Foo { 'Foo' } }
    # No files matching '...\Temp\Foo[0]' were found.
    
    $fileEscaped = [WildcardPattern]::Escape($file)
    switch -File $fileEscaped { foo { 'Foo' } }
    # Foo
    
  • If wildcard expression evaluation is desired, only a single match is permitted.

    $null = 0, 1 | New-Item -Path { "Temp:\Bar$_" } -Value Bar -Force
    
    switch -File Temp:\Bar[0] { Bar { 'Bar' } }
    # Bar
    
    switch -File Temp:\Bar[01] { Bar { 'Bar' } }
    # InvalidOperation: The path cannot be processed because it resolved to more than one file; 
    # only one file at a time can be processed.

Suggested Fix

No response

Metadata

Metadata

Assignees

Labels

issue-doc-bugIssue - error in documentationneeds-triageWaiting - Needs triage

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions