8000 Unix folder structure and naming · Issue #127 · lipkau/PSIni · GitHub
[go: up one dir, main page]

Skip to content

Unix folder structure and naming #127

Open

Description

@tytan15

Description

I prepared an extensive script using PSIni, and in order not to rewrite it, I decided to run PowerShell in Linux.
The module installation proceeded without errors, but it was not possible to use this add-on. After analysis, it turned out that the module was installed in a directory with a structure that did not allow the module to be loaded.
When I changed the structure and changed the name of the directory where the module is located (case sensitive in Unix), it was correctly recognised.

Steps To Reproduce

  1. Start Powershell as a user
    pwsh
  2. Install PIini module
    Install-Module PSIni
  3. List the tree structure
    tree -L 3 -N ~/.local/share/powershell
  4. Received
├── Modules
│  └── PsIni
│    └── 4.0.0
│      ├── CHANGELOG.md
│      ├── LICENSE
│      ├── PSGetModuleInfo.xml
│      ├── PSIni.psd1
│      ├── PSIni.psm1
│      └── README.md

Expected behaviours

With the structure as below, the module is recognised correctly.

├── Modules
│   └── PSIni
│       ├── CHANGELOG.md
│       ├── LICENSE
│       ├── PSGetModuleInfo.xml
│       ├── PSIni.psd1
│       ├── PSIni.psm1
│       └── README.md

Your Environment

System: Zorin OS - based on Ubuntu 22.04
Powershell: 7.5.1

Get-Module PSIni -ListAvailable | Select Name, Version

Name  Version
----  -------
PSIni 4.0.0
$PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.5.1
PSEdition                      Core
GitCommitId                    7.5.1
OS                             Zorin OS 17.3
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Possible Solution

Be consistent in naming directories and files concerning case. In UNIX, this matters, but in Windows, it doesn't bother.
If possible, adjust the module's installation path.

Activity

  1. self-assigned this
    on Jun 11, 2025
  2. trippingtarballs commented on Aug 8, 2025

    @trippingtarballs

    Why is this happening?

    The clue is in the verbose output of the Install-Module command:

    VERBOSE: Searching repository 'https://www.powershellgallery.com/api/v2/FindPackagesById()?id='PSIni'' for ''.
    VERBOSE: Total package yield:'1' for the specified package 'PSIni'.
    VERBOSE: Performing the operation "Install-Module" on target "Version '4.0.0' of module 'PsIni'".

    PowerShell does a lookup of PSIni, matches it to PsIni, and create a folder based on that match: /root/.local/share/powershell/Modules/PsIni/4.0.0/...

    This tells me that PSIni was originally published to the PowerShell Gallery as PsIni.

    Indeed, this metadata is even present in the store listing: https://www.powershellgallery.com/packages/PsIni

    Presumably, somewhere in the history of the project it was decided the module should be known as PSIni and not PsIni, and this change came after the store listing was created.

    What to do about it?

    Honestly, I have no idea ... PowerShell claims to support Linux & macOS, alongside Windows. I don't understand how that can be claimed without provision for case-sensitive filesystems being made.

    As a workaround I will rename the folder on Linux (see replication steps below) after install.

    & {
      Install-Module -Name PSIni -Scope CurrentUser -Force -ErrorAction Stop -Verbose
      $modules=($env:PSModulePath -split [System.IO.Path]::PathSeparator)[0]
      Rename-Item "$modules/PsIni" "$modules/PSIni" -Force -Verbose
      Get-Module -ListAvailable PsIni
      Import-Module PSIni -Force -Verbose
    }

    🤷

    Replication Options

    To replicate on CI

    Using GitHub Actions:

    name: PSIni Case Issue
    on: workflow_dispatch
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - name: Install PSIni
            shell: pwsh
            run: Install-Module PSIni -Scope CurrentUser -Force
            
          - name: Show created folder
            shell: pwsh  
            run: Get-ChildItem ~/.local/share/powershell/Modules/ | Where Name -like "*ini*"
            
          - name: Try import (fails)
            shell: pwsh
            run: Import-Module PSIni -Verbose
    To replicate locally

    Using Podman:

    $ podman run -it --rm mcr.microsoft.com/azure-powershell
    WARNING: image platform (linux/amd64) does not match the expected platform (linux/arm64)
    PowerShell 7.5.0
    
    PS />

    Now you have a Linux-based case-sensitive OS running PowerShell you can replicate these same steps.

    1. Install PSIni:
    PS /> Get-PSRepository | Sort-Object Priority
    
    Name                      InstallationPolicy   SourceLocation
    ----                      ------------------   --------------
    PSGallery                 Untrusted            https://www.powershellgallery.com/api/v2
    
    
    PS /> Install-Module -Name PSIni -Scope CurrentUser -ErrorAction Stop -Force -Verbose
    VERBOSE: Using the provider 'PowerShellGet' for searching packages.
    VERBOSE: The -Repository parameter was not specified.  PowerShellGet will use all of the registered repositories.
    VERBOSE: Getting the provider object for the PackageManagement Provider 'NuGet'.
    VERBOSE: The specified Location is 'https://www.powershellgallery.com/api/v2' and PackageManagementProvider is 'NuGet'.
    VERBOSE: Searching repository 'https://www.powershellgallery.com/api/v2/FindPackagesById()?id='PSIni'' for ''.
    VERBOSE: Total package yield:'1' for the specified package 'PSIni'.
    VERBOSE: Performing the operation "Install-Module" on target "Version '4.0.0' of module 'PsIni'".
    VERBOSE: The installation scope is specified to be 'CurrentUser'.
    VERBOSE: The specified module will be installed in '/root/.local/share/powershell/Modules'.
    VERBOSE: The specified Location is 'NuGet' and PackageManagementProvider is 'NuGet'.
    VERBOSE: Downloading module 'PsIni' with version '4.0.0' from the repository 'https://www.powershellgallery.com/api/v2'.
    VERBOSE: Searching repository 'https://www.powershellgallery.com/api/v2/FindPackagesById()?id='PsIni'' for ''.
    VERBOSE: InstallPackage' - name='PsIni', version='4.0.0',destination='/tmp/747788836'
    VERBOSE: DownloadPackage' - name='PsIni', version='4.0.0',destination='/tmp/747788836/PsIni.4.0.0/PsIni.4.0.0.nupkg', uri='https://www.powershellgallery.com/api/v2/package/PsIni/4.0.0'
    VERBOSE: Downloading 'https://www.powershellgallery.com/api/v2/package/PsIni/4.0.0'.
    VERBOSE: Completed downloading 'https://www.powershellgallery.com/api/v2/package/PsIni/4.0.0'.
    VERBOSE: Completed downloading 'PsIni'.
    VERBOSE: InstallPackageLocal' - name='PsIni', version='4.0.0',destination='/tmp/747788836'
    VERBOSE: Validating the 'PsIni' module contents under '/tmp/747788836/PsIni.4.0.0' path.
    VERBOSE: Test-ModuleManifest successfully validated the module manifest file '/tmp/747788836/PsIni.4.0.0'.
    VERBOSE: Module 'PsIni' was installed successfully to path '/root/.local/share/powershell/Modules/PsIni/4.0.0'.
    
    
    PS /> 
    1. Confirm PSIni is installed:
    PS /> Get-InstalledModule PSIni -Verbose
    
    Version              Name                                Repository           Description
    -------              ----                                ----------           -----------
    4.0.0                PsIni                               PSGallery            Convert hashtable to INI file and back
    
    
    PS /> dir /root/.local/share/powershell/Modules/PsIni/4.0.0
    
        Directory: /root/.local/share/powershell/Modules/PsIni/4.0.0
    
    UnixMode         User Group         LastWriteTime         Size Name
    --------         ---- -----         -------------         ---- ----
    -rw-r--r--       root root        5/17/2025 16:42         4638 CHANGELOG.md
    -rw-r--r--       root root        5/17/2025 16:42         1080 LICENSE
    -rw-r--r--       root root         8/8/2025 14:29         4820 PSGetModuleInfo.xml
    -rw-r--r--       root root        5/17/2025 16:45         1432 PSIni.psd1
    -rw-r--r--       root root        5/17/2025 16:43        21985 PSIni.psm1
    -rw-r--r--       root root        5/17/2025 16:42         2789 README.md
    
    1. Import PSIni module:
    PS /> Import-Module PSIni -Verbose
    VERBOSE: Skipping the Version folder 4.0.0 under Module /root/.local/share/powershell/Modules/PsIni as it does not have a valid module manifest file.
    Import-Module: The specified module 'PSIni' was not loaded because no valid module file was found in any module directory.
    
    
    PS /> Import-Module PsIni -Verbose
    VERBOSE: Skipping the Version folder 4.0.0 under Module /root/.local/share/powershell/Modules/PsIni as it does not have a valid module manifest file.
    Import-Module: The specified module 'PsIni' was not loaded because no valid module file was found in any module directory.
    
    
    PS />
    1. Rename the folder PsIni to PSIni:
    PS /> Rename-Item /root/.local/share/powershell/Modules/PsIni /root/.local/share/powershell/Modules/PSIni -Force -Verbose
    VERBOSE: Performing the operation "Rename Directory" on target "Item: /root/.local/share/powershell/Modules/PsIni Destination: /root/.local/share/powershell/Modules/PSIni".
    
    
    PS />
    1. Finally, try the import once again:
    PS /> Import-Module PSIni -Verbose -Force
    VERBOSE: Loading module from path '/root/.local/share/powershell/Modules/PSIni/4.0.0/PSIni.psd1'.
    VERBOSE: Removing the imported "Import-Ini" function.
    VERBOSE: Removing the imported "Export-Ini" function.
    VERBOSE: Removing the imported "ipini" alias.
    VERBOSE: Removing the imported "epini" alias.
    VERBOSE: Populating RepositorySourceLocation property for module PSIni.
    VERBOSE: Loading module from path '/root/.local/share/powershell/Modules/PSIni/4.0.0/PSIni.psm1'.
    VERBOSE: Exporting function 'Export-Ini'.
    VERBOSE: Exporting function 'Import-Ini'.
    VERBOSE: Exporting function 'Get-AllowedEncoding'.
    VERBOSE: Exporting function 'Invoke-ConditionalParameterValidationEncoding'.
    VERBOSE: Exporting function 'Invoke-ConditionalParameterValidationPath'.
    VERBOSE: Exporting function 'Out-Key'.
    VERBOSE: Exporting function 'Write-DebugMessage'.
    VERBOSE: Exporting alias 'epini'.
    VERBOSE: Exporting alias 'ipini'.
    VERBOSE: Importing function 'Export-Ini'.
    VERBOSE: Importing function 'Import-Ini'.
    VERBOSE: Importing alias 'epini'.
    VERBOSE: Importing alias 'ipini'.
    
    
    PS /> Import-Module PsIni -Verbose -Force
    VERBOSE: Loading module from path '/root/.local/share/powershell/Modules/PSIni/4.0.0/PSIni.psd1'.
    VERBOSE: Removing the imported "Import-Ini" function.
    VERBOSE: Removing the imported "Export-Ini" function.
    VERBOSE: Removing the imported "ipini" alias.
    VERBOSE: Removing the imported "epini" alias.
    VERBOSE: Populating RepositorySourceLocation property for module PSIni.
    VERBOSE: Loading module from path '/root/.local/share/powershell/Modules/PSIni/4.0.0/PSIni.psm1'.
    VERBOSE: Exporting function 'Export-Ini'.
    VERBOSE: Exporting function 'Import-Ini'.
    VERBOSE: Exporting function 'Get-AllowedEncoding'.
    VERBOSE: Exporting function 'Invoke-ConditionalParameterValidationEncoding'.
    VERBOSE: Exporting function 'Invoke-ConditionalParameterValidationPath'.
    VERBOSE: Exporting function 'Out-Key'.
    VERBOSE: Exporting function 'Write-DebugMessage'.
    VERBOSE: Exporting alias 'epini'.
    VERBOSE: Exporting alias 'ipini'.
    VERBOSE: Importing function 'Export-Ini'.
    VERBOSE: Importing function 'Import-Ini'.
    VERBOSE: Importing alias 'epini'.
    VERBOSE: Importing alias 'ipini'.
    
    
    PS /> 
  3. joeskeen commented on Nov 8, 2025

    @joeskeen

    This is indeed a very edge-case issue with cross-platform PowerShell.
    Normally when using PS on Linux/Mac, it behaves as it would on Windows with case-insensitive operations.
    In this case, though, it is not.
    I ran into a hard blocker because of this on my Linux box.
    Is it possible we could bring this up as a bug in the PowerShell repository?

    Edit: Actually there are some related issues:
    PowerShell/PowerShell#17342
    PowerShell/PSResourceGet#1402
    PowerShell/PSResourceGet#1446

    I would say those issues block this one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    0