You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Output-to-file cmdlets should not support wildcards with -Path #6714
Note: This is technically a breaking change; if it is deemed too risky, keep it on file for PowerShell vNext.
Currently, output-to-file cmdlets such as Out-File and Set-Content do support wildcard expression passed to their -Path parameter.
This behavior is problematic in two respects:
Overwriting existing files should be a very deliberate act; the use of wildcards to target whatever happens to match contradicts that.
The utility of targeting an output file implicitly by wildcard is very limited:
If no existing file matches the wildcard expressions, an error occurs.
If more than one file matches the wildcard expression, the behavior is inconsistent:
With some cmdlets, an error occurs (e.g., Out-File, Export-FormatData
In other words: only if the wildcard expression happens to match one existing file does the operation succeed - at which point the clearer and safer choice is to target that file with a literal path.
Other cmdlets (e.g.Set-Content) output to all matching files, which is also problematic.
Ergo: output-to-file cmdlets should treat -Path as an alias of -LiteralPath (similar to how -Path in New-Item is effectively -LiteralPath).
While it makes sense to distinguish between interactive and script use with respect to syntax, I think extending that distinction to features is problematic.
Yes, you can view doing something like
'hi'|Set-Content*.txt
to overwrite all*.txt files in the current folder as convenient, but I think of it as risky, and the use case strikes me as too exotic to outweigh the risks.
At the very least, all output-to-file cmdlets should act consistently in such a scenario, in favor of the only-output-to-ONE-file behavior (as Out-File currently does) ; even documenting the differences won't do, in my opinion, because it's just too hard to remember which cmdlet behaves how.
The wildcard need not be in the leaf of the path. Consider
'hi' | setcontent longdir*/foo.txt
I definitely agree that having Set-Content write to multiple files seems dubious at best. Kenneth Hansen (@khansen00) may remember why we decided to do this.
Wildcard expansion everywhere is intended to mimic traditional shell behaviour. Since it was the shell that did expansion, commands had no control of it and the user had to do explicit quoting. Quoting wildcards in paths in PowerShell is problematic since the expansion is handled in the API, not the shell directly and so you have to double-quote all wildcards. This was such a pain we ended up adding -LiteralPath in V2 (not my favourite thing)
I once started a similar discussion #3174 which was committee reviewed therefore.
While my personal preference would be to treat them as literal paths, I think the current behavior is valid for scripting.
Having wildcard support for input and output even makes it more consistent.
BUT, all cmdlets should behave the same! Apart from file path wildcards, literal paths should be available too. I would go as far to say -Path is ALWAYS with wildcard support and -LiteralPath is a mandatory override.
I have lots of files with square brackets. The way PS handles paths with wildcards always gets me. But that was the initial design of PS and people are using it that way. Maybe something to re-consider in PS7 😀
-Path is ALWAYS with wildcard support and -LiteralPath is a mandatory override.
This distinction is worth observing in general, but there are exceptions, such as with New-Item, where wildcards aren't supported (and make no sense); however, -LiteralPath should be introduced as an alias parameter name there.
The way PS handles paths with wildcards always gets me. But that was the initial design of PS and people are using it that way. Maybe something to re-consider in PS7
Yes, the great -LiteralPath / -Path schism is unfortunate and a perennial pain point.
so you have to double-quote all wildcards.
Bruce Payette (@BrucePay), I assume you meant `-escaping individual wildcard characters inside a single-quoted string or doubly escaping them inside an unquoted or double-quoted string (the alternative is to use [System.Management.Automation.WildcardPattern]::Escape()):
New-Item-Type File 'tmp[a].txt'# create file whose name *looks* like a wildcard pattern# BROKEN, because even though the path matches literally, it is interpreted as a wildcard pattern (by default, `-Path` implied).# What matters is what Get-Item ends up seeing *after* string expansion / quote removal.Get-Item tmp[a].txt # same as: Get-Item -Path tmp[a].txtGet-Item'tmp[a].txt'# sameGet-Item"tmp[a].txt"# same# OK: All of the following target file 'tmp[a].txt' by its exact, literal name:Get-Item-Path 'tmp`[a`].txt'# Note the '...' and the individually `-escaped wildcard chars.Get-Item-Path "tmp``[a``].txt"# Note the '"..." and the *doubly* individually `-escaped wildcard chars.Get-Item-Path tmp``[a``].txt # ditto with no outer quoting, which is like implicit "..."Get-Item-LiteralPath tmp[a].txt # No quoting necessaryGet-Item-Path ([System.Management.Automation.WildcardPattern]::Escape('tmp[a].txt')) # API use
Activity
BrucePay commentedon Apr 24, 2018
Wildcard use is very handy in interactive scenarios. In scripting scenarios, you can use -Literalpath to be precise and avoid wildcard processing.
mklement0 commentedon Apr 24, 2018
While it makes sense to distinguish between interactive and script use with respect to syntax, I think extending that distinction to features is problematic.
Yes, you can view doing something like
to overwrite all
*.txtfiles in the current folder as convenient, but I think of it as risky, and the use case strikes me as too exotic to outweigh the risks.At the very least, all output-to-file cmdlets should act consistently in such a scenario, in favor of the only-output-to-ONE-file behavior (as
Out-Filecurrently does) ; even documenting the differences won't do, in my opinion, because it's just too hard to remember which cmdlet behaves how.BrucePay commentedon Apr 24, 2018
The wildcard need not be in the leaf of the path. Consider
I definitely agree that having
Set-Contentwrite to multiple files seems dubious at best. Kenneth Hansen (@khansen00) may remember why we decided to do this.Wildcard expansion everywhere is intended to mimic traditional shell behaviour. Since it was the shell that did expansion, commands had no control of it and the user had to do explicit quoting. Quoting wildcards in paths in PowerShell is problematic since the expansion is handled in the API, not the shell directly and so you have to double-quote all wildcards. This was such a pain we ended up adding
-LiteralPathin V2 (not my favourite thing)ThreeFive-O commentedon Apr 24, 2018
I once started a similar discussion #3174 which was committee reviewed therefore.
While my personal preference would be to treat them as literal paths, I think the current behavior is valid for scripting.
Having wildcard support for input and output even makes it more consistent.
BUT, all cmdlets should behave the same! Apart from file path wildcards, literal paths should be available too. I would go as far to say -Path is ALWAYS with wildcard support and -LiteralPath is a mandatory override.
I have lots of files with square brackets. The way PS handles paths with wildcards always gets me. But that was the initial design of PS and people are using it that way. Maybe something to re-consider in PS7 😀
mklement0 commentedon Apr 25, 2018
Bruce Payette (@BrucePay): Good point about the wildcard in a directory component; that's perhaps a better use case.
I'll close this issue to discuss the problematic
Set-Contentbehavior separately.ThreeFive-O:
Agreed.
This distinction is worth observing in general, but there are exceptions, such as with
New-Item, where wildcards aren't supported (and make no sense); however,-LiteralPathshould be introduced as an alias parameter name there.ThreeFive-O, Bruce Payette (@BrucePay):
Yes, the great
-LiteralPath/-Pathschism is unfortunate and a perennial pain point.Bruce Payette (@BrucePay), I assume you meant
`-escaping individual wildcard characters inside a single-quoted string or doubly escaping them inside an unquoted or double-quoted string (the alternative is to use[System.Management.Automation.WildcardPattern]::Escape()):mklement0 commentedon Apr 25, 2018
Closed in favor of #6729.