Eric
Eric

Reputation: 63

Powershell get case sensitive path as displayed in windows

I'm looking for a way to get the my local path that includes any camel cases that are used in the names. The primary reason is so I can use the same path to make a call in windows wsl. For example, in windows I can call a file as

c:\FoO\bar.txt 
c:\Foo\Bar.txt

and windows will display it as c:\foo\bar.txt. When I try to enter the WSL with bash I need to know the actual path since Linux is case sensitive.

I have tried using

$PSScriptRoot
Split-path C:\FoO\Bar.txt
(get-Item c:\Foo\Bar.txt).FullName

but they will only provide the path that to call the script.
How do I get my path as it's displayed in the windows os? I can't just call the full path of the file I need since I can't guarantee the root directory it starting from. I also don't want to burn up cycles doing a find.

Upvotes: 5

Views: 3284

Answers (5)

aetonsi
aetonsi

Reputation: 227

A super simple (but also relatively slow) solution that can work if you have to get just the Name or Extension, is using cmd.exe's dir /b command:

$path = 'C:\TMP\NEW FOLDER\MYICON.ico'
# the actual name of the file is myicon.ICO

$myFile = (Get-Item $path).FullName
$caseSensitiveName = & cmd.exe /c dir /b $myFile
$caseSensitiveExtension = [System.IO.Path]::GetExtension($caseSensitiveName)
$caseSensitiveBasename = [System.IO.Path]::GetFileNameWithoutExtension($caseSensitiveName)

">name: $caseSensitiveName"
">basename: $caseSensitiveBasename"
">extension $caseSensitiveExtension"

This prints:

>name: myicon.ICO
>basename: myicon
>extension .ICO

BONUS: getting the folder path this way, is way harder than what i thought, because even dir without /b presents the path AS PASSED instead of the real one, so we have to get smarter... (or crazier, because this spawns cmd.exes until the path is parsed, folder by folder, backwards).

# continuing from the example above: the actual dir path is C:\tmp\nEW fOLDer, not C:\TMP\NEW FOLDER as above
$caseSensitiveFullName = ''
while (1) {
    if ([System.IO.Path]::GetPathRoot($myFile) -eq $myFile) {
        $caseSensitiveFullName = $myFile + $caseSensitiveFullName
        break
    }
    $myFileParent = [System.IO.Path]::GetDirectoryName($myFile)
    $caseSensitiveParent = (& cmd.exe /c dir /ad/b $myFileParent) | Where-Object { $_ -ieq [System.IO.Path]::GetFileName($myFile) }
    $caseSensitiveFullName = $caseSensitiveParent + '\' + $caseSensitiveFullName
    $myFile = $myFileParent
}
$caseSensitiveFullName = $caseSensitiveFullName.TrimEnd('\')
$caseSensitiveDirectory = ([System.IO.Path]::GetDirectoryName($caseSensitiveFullName))

">directory: $caseSensitiveDirectory"
">fullname: $caseSensitiveFullName"

This prints:

>directory: C:\tmp\nEW fOLDer
>fullname: C:\tmp\nEW fOLDer\myicon.ICO

Upvotes: 0

Floris Devreese
Floris Devreese

Reputation: 3687

from windows 10 onwards, the Target property is empty.
(Get-Item '....') doesn't contain any property that holds the case sensitive name.

however, when getting all child items of a folder, you get all the names case sensitive.

so my solution is like this:

$myCaseInsensitiveFileName = 'c:\FoO\bar.txt'

$allFiles = Get-ChildItem 'c:\' -Recurse
$caseSensitiveName = $allFiles.FullName | Where-Object { $_.FullName -eq $myCaseInsensitiveFileName }

$caseSensitiveName holds C:\Foo\Bar.txt.

note:

  • this can be optimized, but you get the idea.
  • the -eq operator compares strings case insensitive

Upvotes: 1

Sambardo
Sambardo

Reputation: 754

What you want is to look at the Target property you get back from Get-Item. Fullname will come back however you typed it initially, but Target is actually a code property that seems to get the raw path of the object.

(get-Item c:\Foo\Bar.txt).Target

Upvotes: 3

rhmccullough
rhmccullough

Reputation: 105

I have some automated ways to do it.
See http://ContextKnowledge.blog
"myenv package for Windows 10 + Cygwin + WSL/Ubuntu"
The package includes a few short shell scripts
which find the information and record it in environment variables.
If these shell scripts don't work for you, contact me with more details
and I'll figure out something that will.

Upvotes: -3

rhmccullough
rhmccullough

Reputation: 105

Find the directory with Windows File Explorer and it shows full path name.
Find the directory in WSL or PowerShell and "pwd" or "echo $PWD" gives full path name.
Add directory to PATH in $HOME/.profile and you don't need full path name.

Upvotes: -3

Related Questions