Repository navigation
Output-to-file cmdlets should not support wildcards with -Path #6714
Description
Activity
Wildcard use is very handy in interactive scenarios. In scripting scenarios, you can use -Literalpath to be precise and avoid wildcard processing.
mklement0 commented
on Apr 24, 2018 ContributorAuthorMore actionsWhile 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
*.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.The wildcard need not be in the leaf of the path. Consider
'hi' | setcontent longdir*/foo.txtI 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)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 commented
on Apr 25, 2018 ContributorAuthorMore actionsBruce 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.BUT, all cmdlets should behave the same!
Agreed.
-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,-LiteralPathshould 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
ThreeFive-O, Bruce Payette (@BrucePay):
Yes, the great
-LiteralPath/-Pathschism 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].txt Get-Item 'tmp[a].txt' # same Get-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 necessary Get-Item -Path ([System.Management.Automation.WildcardPattern]::Escape('tmp[a].txt')) # API use
mklement0 commented
on Apr 25, 2018 ContributorAuthorMore actionsClosed in favor of #6729.
- addedIssue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifResolution-AnsweredThe question is answered.The question is answered.
on May 26, 2018
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-FileandSet-Contentdo support wildcard expression passed to their-Pathparameter.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:
Out-File,Export-FormatDataSet-Content) output to all matching files, which is also problematic.Ergo: output-to-file cmdlets should treat
-Pathas an alias of-LiteralPath(similar to how-PathinNew-Itemis effectively-LiteralPath).Environment data
Written as of:
PowerShell Core v6.0.2