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
Set-Location preserves case instead of matching filesystem on case-insensitive/preserving system #5678
Working directory ends in `\foo`. (note the difference in case)
Remarks
I originally thought this issue belonged with #1273, but that is about tab completion and globbing on non-Windows platforms, whereas this does not involve tabbing or globbing, and is on Windows.
This problem can cause problems with git and other things.
If I use cmd.exe instead, it gives the expected/desired results.
On case-sensitive systems, I don't know what the correct behavior should be (reject it if the path doesn't exist, or automagically switch to the fs-matching case)... perhaps it should be controlled by the same settings as in #1273.
Unfortunately, this has turned out to be much more complicated than I anticipated. [DirectoryInfo]::GetFiles() and GetDirectories() aren't working correctly on macOS. I'll need to open a issue for corefx. https://github.com/dotnet/corefx/issues/26797
On case-sensitive systems, I don't know what the correct behavior should be (reject it if the path doesn't exist, or automagically switch to the fs-matching case)...
There's at least one case in which the path should be rejected:
If there's ambiguity due to the presence of more than 1 case-variant folder: e.g, if you specify test and both TEST and Test exist.
If there is no ambiguity - just 1 case-variant match - I suppose targeting that automatically is an option, but note that for consistency we'd then have to implement the same logic wherever file/directory paths are accepted, such as Get-Content.
I suspect that that behavior would ultimately be too obscure and I suggest we keep a clean separation between:
literal names that must be case-exact on case-sensitive filesystems.
(possibly opt-in) case-insensitive tab-completion and wildcard matching, where ambiguity can be resolved by cycling through / returning multiple matches.
https://github.com/dotnet/corefx/issues/26797 is indeed resolved, but the issue at hand persists, and it is PowerShell that is the culprit (in the following examples, a Test directory is created, and it is accessed via its all-lowercase variant, test):
PS> mkdir -p /tmp/Test; Set-Location/tmp/test; $PWD.Path/tmp/test # !! *input* case was preserved, even though the actual name is a case variant
Using .NET Core does NOT exhibit this behavior:
PS> mkdir -p /tmp/Test; [Environment]::CurrentDirectory ='/tmp/test'; [Environment]::CurrentDirectory
/private/tmp/Test # OK: actual dir. name is reflected in the last path component
(Note that /tmp is a symlink to /private/tmp on macOS.)
Windows:
Unlike on macOS, it is .NET itself and, I suspect, ultimately the Windows API that behaves this way, so if we want to fix this behavior, we'll have to do it in PowerShell (as cmd.exe apparently does):
PS>$null= mkdir -Force $env:TEMP\Test; [Environment]::CurrentDirectory ="$env:TEMP\test"; [Environment]::CurrentDirectory
C:\Users\jdoe\AppData\Local\Temp\test # !! *input* case was preserved.
Note that the behavior doesn't just affect Set-Location (cd), but also other cmdlets such as Get-Item.
Michael Klement (@mklement0) Thanks! I agree that it is PowerShell issue.
Perhaps we should ask a more general question -see #1273 and #7221 last comment) - how much should we be case-sensitive/-insensitive on every platform?
on Windows, API preserves case but all comparisions is case-insensitive. PowerShell follow this.
on MacOs, API preserves case but all comparisions is case-insensitive. Currently PowerShell doesn't follow this. Bug? Should? I think yes.
I think literal names should never be automatically case-corrected on case-sensitive filesystems, to avoid ambiguity.
It makes sense to offer case-insensitivity for (a) tab-completion and (b) filename globbing, but I wonder if it should require an explicit opt-in (perhaps via preference variables), at least for globbing.
Otherwise, users may be surprised if Get-Item test doesn't find .\Test, but Get-Item test* does, for instance.
That said, as stated in #1273 (comment), the tricky thing is that a preference variable that controls globbing case-sensitivity, if set in the global scope, would potentially change the behavior of all scripts run in-process, unless they explicit set the preference variable to the default in their scope.
Given that, perhaps the answer is to:
categorically use case-insensitive globbing (and tab-completion) on all platforms, even on Linux.
offer case-sensitive globbing, if desired, only:
via the filesystem provider's -Filter parameter (though that could be confusing)
via a -CaseSensitive (sic) switch added to Resolve-Path - for consistency, that switch would then have to be honored on Windows and macOS too, however (just documenting it as being ignored on these platform may not be enough to avoid confusion).
There ultimately is no good solution here, but what appeals to me about the latter solution is its simplicity:
As a user, all you need to remember is that PowerShell wildcards are case-insensitiveeverywhere by default.
Getting case-sensitive filename globbing, if needed (probably rarely), must be requested explicitly with -Resolve-Path -CaseSensitive and perhaps also the filesystem provider's -Filter parameter.
I'm starting to think that the latter is not a good idea, though: on the one hand, there already are differences between -Filter and PS wildcards on Windows, but they are subtle and don't affect the majority use cases; on the other hand, -Filter is often used for performance reasons alone, and having it be case-sensitive is then an inconvenience at best, and a subtle source of bugs at worst.
No new preference variables and therefore no associated issues with global state ("convention over configuration").
Obviously, the behavior would need documenting in about_wildcards.
Activity
SteveL-MSFT commentedon Feb 2, 2018
Unfortunately, this has turned out to be much more complicated than I anticipated. [DirectoryInfo]::GetFiles() and GetDirectories() aren't working correctly on macOS. I'll need to open a issue for corefx. https://github.com/dotnet/corefx/issues/26797
iSazonov commentedon May 8, 2018
DotNet Issue was closed without resolution. 😕
SteveL-MSFT commentedon May 9, 2018
I'll investigate this again once I find some time.
iSazonov commentedon May 9, 2018
Maybe we need to follow C# as discussed in #6833 and develop language means for creating portable scripts.
mklement0 commentedon Sep 3, 2018
Dan Thompson (@jazzdelightsme):
There's at least one case in which the path should be rejected:
If there's ambiguity due to the presence of more than 1 case-variant folder: e.g, if you specify
testand bothTESTandTestexist.If there is no ambiguity - just 1 case-variant match - I suppose targeting that automatically is an option, but note that for consistency we'd then have to implement the same logic wherever file/directory paths are accepted, such as
Get-Content.I suspect that that behavior would ultimately be too obscure and I suggest we keep a clean separation between:
literal names that must be case-exact on case-sensitive filesystems.
(possibly opt-in) case-insensitive tab-completion and wildcard matching, where ambiguity can be resolved by cycling through / returning multiple matches.
mklement0 commentedon Sep 3, 2018
As for the issue at hand:
macOS:
https://github.com/dotnet/corefx/issues/26797 is indeed resolved, but the issue at hand persists, and it is PowerShell that is the culprit (in the following examples, a
Testdirectory is created, and it is accessed via its all-lowercase variant,test):Using .NET Core does NOT exhibit this behavior:
(Note that
/tmpis a symlink to/private/tmpon macOS.)Windows:
Unlike on macOS, it is .NET itself and, I suspect, ultimately the Windows API that behaves this way, so if we want to fix this behavior, we'll have to do it in PowerShell (as
cmd.exeapparently does):Note that the behavior doesn't just affect
Set-Location(cd), but also other cmdlets such asGet-Item.iSazonov commentedon Sep 4, 2018
Michael Klement (@mklement0) Thanks! I agree that it is PowerShell issue.
Perhaps we should ask a more general question -see #1273 and #7221 last comment) - how much should we be case-sensitive/-insensitive on every platform?
For example, if a user accidentally types
dir /Etcwe could test that/Etcdoesn't exists and then try/etc- is the behavior acceptable for Linux users? If yes, we could easily resolve the Issue and Location completion should be case-insensitive #1273 in that way I suggested in Make TabCompletion case-insensitive for file names on Unix (2-nd attempt) #7221.mklement0 commentedon Sep 4, 2018
Ilya (@iSazonov): Please see #5678 (comment) above.
In short:
I think literal names should never be automatically case-corrected on case-sensitive filesystems, to avoid ambiguity.
It makes sense to offer case-insensitivity for (a) tab-completion and (b) filename globbing, but I wonder if it should require an explicit opt-in (perhaps via preference variables), at least for globbing.
Otherwise, users may be surprised if
Get-Item testdoesn't find.\Test, butGet-Item test*does, for instance.For ad-hoc use (as well as for internal use in generating completions), adding a
-CaseInsensitiveswitch toResolve-Pathdoes make sense.That said, as stated in #1273 (comment), the tricky thing is that a preference variable that controls globbing case-sensitivity, if set in the global scope, would potentially change the behavior of all scripts run in-process, unless they explicit set the preference variable to the default in their scope.
Given that, perhaps the answer is to:
categorically use case-insensitive globbing (and tab-completion) on all platforms, even on Linux.
offer case-sensitive globbing, if desired, only:
-Filterparameter (though that could be confusing)-CaseSensitive(sic) switch added toResolve-Path- for consistency, that switch would then have to be honored on Windows and macOS too, however (just documenting it as being ignored on these platform may not be enough to avoid confusion).iSazonov commentedon Sep 5, 2018
I agree with tab-completion but globbing - I think users will be surprised that
Copy-Item -Path $env:TEMP\T*will copy$env:TEMP\teston Linux.mklement0 commentedon Sep 5, 2018
There ultimately is no good solution here, but what appeals to me about the latter solution is its simplicity:
As a user, all you need to remember is that PowerShell wildcards are case-insensitive everywhere by default.
-Resolve-Path -CaseSensitiveand perhaps also the filesystem provider's-Filterparameter.-Filterand PS wildcards on Windows, but they are subtle and don't affect the majority use cases; on the other hand,-Filteris often used for performance reasons alone, and having it be case-sensitive is then an inconvenience at best, and a subtle source of bugs at worst.No new preference variables and therefore no associated issues with global state ("convention over configuration").
Obviously, the behavior would need documenting in about_wildcards.