Powershell: Importing modules by name is case sensitive

Created on 3 Aug 2016  路  19Comments  路  Source: PowerShell/PowerShell

Steps to reproduce

Start a PowerShell session.
Remove-Module PSReadline
Import-Module PSReadline

Expected behavior

Expect to be able to re-import PSReadline. This works with other modules.

Actual behavior

Error reporting module can't be found.

psreadlineerror

Environment data

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.10032.0
PSEdition                      PowerShellCore
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   3.0.0.0
GitCommitId                    v6.0.0-alpha.7
CLRVersion
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
Resolution-Fixed WG-DevEx-Portability

Most helpful comment

I believe that as a general principle, PowerShell should be as case-preserving/case insensitive as possible while not breaking the underlying OS.

So in the case of the Unix File system manipulation and environmental variables - these directly affect the underlying OS and integration with other tools so we have to be case sensitive.

In the case of PowerShell variable names - there is no interaction between them and the underlying OS so we should be case insensitive.

So then issue with Module Names is that they are a tweener. On the one hand there is a strong mapping to an underlying OS - a foldername. On the other hand, theyy refer to a pure PowerShell concept - a PowerShell Module. So you could argue it either way.

To me, the thing that pushes this decisively to the Case Insensitive solution is the effect the issue has on Ecosystem sharing. If module names are case sensitive in Unix, then Tom might publish Module TEST and Mary might publish Module test. But then if a Windows users tries to use both these modules, they are going to collide and they fail.

I'm going to propose an acid test we need to apply: Does case sensitivity break sharing artifacts between Windows and Linux? If the answer is yes, then the prima facia answer should be that we should be case insensitive.

Ergo - Module names should be case insensitive.

Does that sound right?

All 19 comments

You look like you're running on Linux, which is case-sensitive. Try Import-Module PSReadLine with a capital L (or let tab-completion finish it).

The Linux filesystem is case-sensitive but that doesn't "necessarily" mean PS Core should be case-sensitive WRT module names. I get that module names are backed by directory names and that complicates things - what if an author creates two (or more) module folders that vary by case only e.g. Foo, foo, FOO. If PS Core uses case-insensitive module names, what should Import-Module foo do in this scenario? Perhaps it should error indicating multiple module names that vary only by case is not allowed (and is just dumb in the first place)? Then again, this just might be my bias speaking i.e. I think this is one area that *nix got it wrong. :-)

This is #781, which as closed as duplicate of #706.
I think we should re-open it and track separately, because #706 is too generic.

@andschwa Another question is why is casing different in PowerShell 6.0.0.7? In PowerShell 5.1 the name is PSReadline. On PS Gallery the name is PSReadline. In PowerShell 6.0.0.7 is PSReadLine.

/cc @lzybkr

@andschwa and I discussed this - I was inconsistent in the naming (the code uses both PSRead_L_ine and PSRead_l_ine.)

I'm slightly embarrassed about that, but we decided that if it's Console.ReadLine, and we're on an OS where case matters, it probably should have been PSReadLine and I should make it consistent.

I suppose there is an argument against the cap L though - GNU readline isn't GNU read_line - so readline is one word, not two.

So... did I just convince myself @andschwa and I were wrong to use PSRead_L_ine? Hmm...

@lzybkr I believe that we went with PSRead_L_ine since the source files (PSReadLine.psm1 etc.), classes (PSConsoleReadLine), and repository (lzybkr/PSReadLine) were capitalized as such.

It was only a module name here or there that used PSRead_l_ine.

@andschwa @lzybkr I would just like to see consistent naming with Windows. Especially because Linux cares about casing. I don't care if it's "l" or "L" as long as it's the same case everywhere.

I thought I had tried a number of casings including what I see with Get-Module but I'll try again.

Ok. Now that I was more careful I found import-module PSReadLine works. Interesting though Remove-Module psreadline works. Casing drives me crazy in Linux but I suppose I'll get used to it.

That Remove-Module psreadline works is... very interesting.

I'm in agreement that we should investigate making modules case-insensitive.

Easily explained - Remove-Module works against our internal list of module names. That list is case-_in_sensitive.

Import-Module imports via the path, which is search with a case sensitive search. We do need to update the search.

At issue is how to do that search - case-insensitive from the start, or start case-sensitive, and if that fails, search again with case-insensitive.

I think it's a bad idea to be case sensitive about module names.

First, if core is case sensitive, it needs to be that everywhere, including
on Nano (even on Windows I can have multiple modules with the same name, if
I put them in different folders).

Second, if we can make PSReadLine _and_ PSReadline, what happens when you
try to publish it, or, heck, have a conversation about it?

Seems like the gold standard here is the existing modules (even if most of
them won't work in core) and gallery...

PostScript:

I think if you actually wanted to keep things simple here, you would to the traditional route for things that must be unique in Linux (like user names) and force them to be all lowercase in the file system.

I'm with Jaykul here. A module name is NOT a folder. It just happens to be backed by one, ergo, we shouldn't feel bound by the rules of the underlying FS. The behaviour that is correct is that of the remove-module command. What if modules and scripts were to come from devices other than those exposed by filesystemprovider? Let's say, on an embedded powershell, where instead there's a solidstatestorageprovider or something. (This is something I tried to raise a conversation about a few years ago on PSMVP: Why aren't we using the IContentReader indirection to source scripts and modules? I get it that the reason is about performance and it seems like overarchitecting to wrap streams in that interface, but I digress... )

I believe that as a general principle, PowerShell should be as case-preserving/case insensitive as possible while not breaking the underlying OS.

So in the case of the Unix File system manipulation and environmental variables - these directly affect the underlying OS and integration with other tools so we have to be case sensitive.

In the case of PowerShell variable names - there is no interaction between them and the underlying OS so we should be case insensitive.

So then issue with Module Names is that they are a tweener. On the one hand there is a strong mapping to an underlying OS - a foldername. On the other hand, theyy refer to a pure PowerShell concept - a PowerShell Module. So you could argue it either way.

To me, the thing that pushes this decisively to the Case Insensitive solution is the effect the issue has on Ecosystem sharing. If module names are case sensitive in Unix, then Tom might publish Module TEST and Mary might publish Module test. But then if a Windows users tries to use both these modules, they are going to collide and they fail.

I'm going to propose an acid test we need to apply: Does case sensitivity break sharing artifacts between Windows and Linux? If the answer is yes, then the prima facia answer should be that we should be case insensitive.

Ergo - Module names should be case insensitive.

Does that sound right?

Guys, please note that it isn't about "Windows is case-insensitive and Linux is not". That's "most common Windows file systems are case-insensitive" and "most common Linux file systems are case-sensitive". And, AFAIK, macOS is case-insensitive too. You could switch this option either on Windows, on Linux or on macOS.

That decision (at least about the file names) shouldn't be tied to platform, but to underlying FS (and every OS could at once mount multiple file systems with different settings).

Noticing that $env variables are case-sensitive as well. $env:PSMODULEPATH does not equal $env:PSModulePath (On MacOS)

Environment variables on Linux are case sensitive.

This needs to get fixed along with #706. Adding it to the usability project.

Based on @jpsnover's reply and the logic that the @PowerShell/powershell-committee landed on in #706, we should close on the fact that importing two modules with the same case-insensitive names should have the same behavior as whatever happens when you import two modules with the same name from different paths (either an error, overwriting the existing one in memory, or silently doing nothing).

Was this page helpful?
0 / 5 - 0 ratings