Test-path with case sensitive

Tagged: 

This topic contains 9 replies, has 5 voices, and was last updated by Profile photo of Curtis Smith Curtis Smith 1 year, 7 months ago.

  • Author
    Posts
  • #31205
    Profile photo of ofergenat
    ofergenat
    Participant

    Hi,
    I need to find a way to check a CSV file that contains lines of UNC paths and make sure the physical path really exist in the same case.
    I couldn't find an operator (-cmatch) for case sensitive in test-path cmdlet.
    Any other idea please?

  • #31206
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    Maybe something like this. I know there is a way to get just the directory from get- child item. Man I need to get a PC for home

    Maybe
    If(test-path $csvitem){set-location $csvitem}
    $path = $(get-location).Path
    if($path -ceq $csvitem){ do something}

  • #31207
    Profile photo of Don Jones
    Don Jones
    Keymaster

    The thing is that the actual Windows file system isn't case-sensitive. It preserves case as typed, but it doesn't differentiate during comparisons. That's why Test-Path doesn't. As Mark points out, your best logic is something like...

    $path_to_test = "C:\Some Mixed Case Path"
    $exists = $true
    if ((Test-Path $path_to_test)) {
    $dir = dir $path_to_test
    if ($dir.name -cneq $path_to_test) {
    $exists = $false
    }
    } else {
    $exists = $false
    }

    I'm not sure why -match or -cmatch would be right for you, but perhaps there's something about what you're doing that you haven't shared.

  • #31214
    Profile photo of ofergenat
    ofergenat
    Participant

    Thanks for the answers, I took your advice and created this:

    $PathToTest = @("C:\WINdows", "C:\Program Files","D:\backup","D:\CourserA")
    $AllNotMatch = ''
    $AllMatch = ''
    $AllNotExist = ''
    foreach ($Path in $PathToTest)
    {
        if ((Test-Path $PathToTest))
            {
            $Dir = dir $Path
            if ($Dir.DirectoryName -cne $Path)
                {
                $AllNotMatch += $Path
                Write-Warning "$Path - does not match the physical case"
                }
            else
                {
                $AllMatch += $Path
                Write-host "$Path - matches the physical case" -F Green
                }
            }
        else
            {
            $AllNotExist += $Path
            Write-Warning "$Path - path does not exist"
            }
    }
    

    But this code still has issues:
    – For some reason I noticed that 2 paths from the array get to be a different object so for example "D:\backup" is different object than "D:\CourserA" and thus it doesn't have a property called DirectoryName which I need to use.
    – Another issue is that I noticed that when using dir "D:\CourserA" command with a mix case it still shows the physical folder name in the same mix case although it's not really so.

  • #31215
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    Maybe

    If(test-path $csvitem){set-location $csvitem}
    $path = $(get-location).Path
    if($path -ceq $csvitem){ do something}

  • #31216
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    There are a couple of problems here.

    1) Get-ChildItem (dir) will return a collection of all the files and folders in the "Path" you are supplying, so when you are checking with your if statement "$Dir.DirectoryName -cne $Path", in the example of "C:\WINdows" you are actually checking

    C:\WINdows C:\WINdows C:\WINdows C:\WINdows C:\WINdows -cne C:\WINdows

    Obviously that is not what you want. You should used get-item, not get-childitem

    2) When you provide an absolution or relative path, the returned result matches the case you supplied. This is the same for Get-Item, Get-ChildItem, Set-Location, Get-Location, etc.

    IE.

    PS C:\> (Get-Item "C:\WINdows").Fullname
    C:\WINdows
    PS C:\> (Get-Item "C:\windows").Fullname
    C:\windows
    PS C:\> (Get-Item "C:\WINDOWS").Fullname
    C:\WINDOWS
    

    This means that no mater what, if you use an absolute or relative path, your case will always match your CSV input.

    The only why I have found so far to get PowerShell to return the actual case of the folder is by making PowerShell search and find it with a wildcard

    PS C:\> (Get-Item "C:\WINdows*").Fullname
    C:\Windows
    PS C:\> (Get-Item "C:\windows*").Fullname
    C:\Windows
    PS C:\> (Get-Item "C:\WINDOWS*").Fullname
    C:\Windows
    

    This will be problematic, of course, for cases where the wildcard causes additional matches, such as Program Files on x64 machines.

    PS C:\> (Get-Item "C:\pRogrAM FilES*").Fullname
    C:\Program Files
    C:\Program Files (x86)
    

    You would need to place your wildcard in a location where it would not cause you to get additional results you did not intend.

    PS C:\> (Get-Item "C:\pRogrAM* FilES").Fullname
    C:\Program Files
    

    It's not great, but it's functional

    $PathToTest = @("C:\WINdow*s", "C:\Program File*s","D:\backu*p","D:\Courser*A")
    $AllNotMatch = ''
    $AllMatch = ''
    $AllNotExist = ''
    foreach ($Path in $PathToTest)
    {
        if ((Test-Path $PathToTest))
            {
            $Dir = Get-Item $Path
            $Path = $Path.Replace("*", "")
            if ($Dir.Fullname -cne $Path)
                {
                $AllNotMatch += $Path
                Write-Warning "$Path - does not match the physical case"
                }
            else
                {
                $AllMatch += $Path
                Write-host "$Path - matches the physical case" -F Green
                }
            }
        else
            {
            $AllNotExist += $Path
            Write-Warning "$Path - path does not exist"
            }
    }
    
  • #31220
    Profile photo of ofergenat
    ofergenat
    Participant

    Thanks Curtis that was very helpful.
    I think it wont be an issue to add a * on the begging of all the UNC paths (on the first folder level).
    I agree that it's not that great at all (and hope I won't run into issues), I was really under the impression that it would be very easy to do with PowerShell.

  • #31226
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Unfortunately it's not PowerShell's fault here. While NTFS is a case sensitive file system, the Windows operating environment (API, .Net, commandline, etc) is not. PowerShell is built on .Net and it is .Net that reads and returns the path the way it does. Maybe cygwin can provide some options for you. Since it runs a POSIX environment, it should keep your path case. This is of course theory as I have not used it.

  • #31243
    Profile photo of Tim Curwick
    Tim Curwick
    Participant

    Curtis,

    The trick to leveraging wildcards with only a single desired match, is to give it a wildcard with only one possible interpretation. The easiest way is to put the last letter in square brackets.

    PS C:\> (Get-Item "C:\pRogrAM FilE[S]").Fullname
    C:\Program Files
    
  • #31255
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Nice Tim

You must be logged in to reply to this topic.