Search code examples
powershellpowershell-2.0powershell-4.0powershell-5.0

Like behaviour on different Powershell versions


This code works well in Powershell 5+ but doesn't work in Powershell 4.0 and 2.0:

$DaysToDelete = 2

$targets = "profile/Default",
           "profile/Profile 1",
           "profile/Profile 2",
           "profile/Profile 3",
           "profile/Profile 4"

$special = @("chromium", "64")

$profiles = Get-ChildItem "C:\" -Directory -Force |
    Where-Object Name -In $special |
    Select-Object -ExpandProperty FullName

$chromeDir = "C:\Users\*\AppData\Local\Google\Chrome\User Data\Default"
$chromeSetDir = "C:\Users\*\Local Settings\Application Data\Google\Chrome\User Data\Default"

$Items = @("*Archived History*",
            "*Cache*",
            "*Cookies*",
            "*History*",
            "*Top Sites*",
            "*Visited Links*",
            "*Web Data*")

$profiles | ForEach-Object {
    foreach($target in $targets) {
        $profile = Join-Path $_ $target

        $items | ForEach-Object {
        $item = $_ 
        Get-ChildItem $profile, $chromeDir, $chromeSetDir -Recurse -Force -ErrorAction SilentlyContinue |
            Where-Object { ($_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete))  -and $_.Directory -like $item} | ForEach-Object { 
            $path = Join-Path $_.DirectoryName $_
            Remove-Item $path -force -Verbose -recurse -ErrorAction SilentlyContinue }
         }

    }
}

I revealed that the piece which breaks the execution is

-and $_.Directory -like $item

It works fine on PS 5+ (Windows 10) but finds nothing alike pattern on PS 4 (Windows 7). Chrome version and its directory hierarchy are the same on both machines: 59.0.3071.115 (Official Build) (64-bit).

Starting script on Win10 with version specification alike

powershell.exe -Version 4.0

gave nothing, it ran fine anything. I am not so fluent in Powershell version-specifics, so gurus are welcomed to propose any suggestions. How to make the script version-independent?

UPDATE: Here is the full code, but it gives nothing valuable. I verified all the places and exactly localized that problem line is the above.

Another interesting moment: I discovered that problem is not in the like clause per se, but in the combination of like and $_.CreationTime check:

$_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete) -and $_.Directory -like $item

If I put either of these conditions by itself, all is working fine, but if I combine them into single compound condition, nothing is returned, though there are folders that meet both conditions.

I cannot explain this in any way.


Solution

  • I mentioned this in the comments; am not sure if it was clear enough, and whether this is the whole issue.

    As per your original question, this line will not work. This is not dependent on the PowerShell version.

    $_.Directory -like $item
    
    • When Get-ChildItem finds files, it will return a System.IO.FileInfo class object.

      • Directory is a property of the FileInfo class, so files will have this property.
      • Directory is of the type DirectoryInfo.
    • When Get-ChildItem finds folders/directories, it will return a System.IO.DirectoryInfo class object.

      • DirectoryInfo objects do not have a Directory property.
      • They have Parent, which also returns a System.IO.DirectoryInfo object
    • In either case, you are dealing with an object and comparing it to a string. When really you probably want to compare the folder Name to a string.
      Edit: True for Windows 8.1 running v5.1.14409.1005; expect to be the same for older OSes.
      False for Windows 10 running PS v5.1.143993.1480; expect to be the same on Server 2016. Not sure how the Name/FullName property is being automagically evaluated...


    Get-ChildItem -File      | Where {$_.Directory      -like "*test*"}   # not ok: comparing object to string.
    Get-ChildItem -Directory | Where {$_.Directory.Name -like "*test*"}   # not ok: DirectoryInfo object does not have Directory property
    
    Get-ChildItem -File      | Where {$_.Directory.Name -like "*test*"}   # ok
    Get-ChildItem -Directory | Where {$_.Parent.Name    -like "*test*"}   # ok