-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
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
break
ing 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