Page 1 of 1

Where-Object gives two different results using a equivalent syntax

Posted: 2021-Jul-26, 6:09 pm
by MigrationUser
16 Dec 2020 22:55
RedHut


I'm trying to understand why I get a different result from the two equivalent where-object syntax.

Basically I get a different result from using ? {$_.CreationTime -lt $_.LastWriteTime} versus ? CreationTime -lt LastWriteTime on a file object.

Here is the test case which gives the same result each time:

Code: Select all

$folder = 'mymediafilesfolder'
get-child-item $folder |ft name,CreationTime,LastWriteTime

Name     CreationTime        LastWriteTime     
----     ------------        -------------     
02 - feb 08.12.2020 04.59.37 10.12.2020 03.50.23

gci $folder |ft name,CreationTime,LastWriteTime

Name                              CreationTime        LastWriteTime     
----                              ------------        -------------     
20200201-DJI_0902.MP4     10.12.2020 03.50.23 01.02.2020 20.50.48
20200201-DJI_0903.MP4     08.12.2020 13.20.33 01.02.2020 20.55.48
20200201-DJI_0904.MP4     08.12.2020 04.59.37 01.02.2020 21.00.50

gci $folder |ft name,CreationTime,LastWriteTime | ? CreationTime -lt LastWriteTime

Name                              CreationTime        LastWriteTime     
----                              ------------        -------------     
20200201-DJI_0902.MP4     10.12.2020 03.50.23 01.02.2020 20.50.48
20200201-DJI_0903.MP4     08.12.2020 13.20.33 01.02.2020 20.55.48
20200201-DJI_0904.MP4     08.12.2020 04.59.37 01.02.2020 21.00.50

gci $folder |ft name,CreationTime,LastWriteTime | ? {$_.CreationTime -lt $_.LastWriteTime}

No items match the filter
According to the docs on this site, the two ways of writing comprising statements should give the same result, but the don't. Why is it behaving this way? Strangely enough, this code returns a result:

Code: Select all

gci $folder |ft name,LastWriteTime,CreationTime | ? {$_.CreationTime -eq $_.LastWriteTime}

Name                              LastWriteTime       CreationTime       
----                              -------------       ------------       
20200201-DJI_0902.MP4     01.02.2020 20.50.48 10.12.2020 03.50.23
20200201-DJI_0903.MP4     01.02.2020 20.55.48 08.12.2020 13.20.33
20200201-DJI_0904.MP4     01.02.2020 21.00.50 08.12.2020 04.59.37
The behaviour is not logical to me but apologies if my confusion is from not understanding basic concept.

----------------------------

#2 17 Dec 2020 01:23
Simon Sheppard


Re: Where-Object gives two different results using a equivalent syntax

Try changing the |ft into |select

Code: Select all

gci $folder |SELECT name,CreationTime,LastWriteTime | ? {$_.CreationTime -lt $_.LastWriteTime}
I think what is happening here is the table formatting is converting everything into strings
and then your comparison is being fed a bunch of effectively random strings instead of neat PowerShell objects

An interesting question is why does your -eq comparison return True?
Try replacing one of the values with $Null and see what happens.

Last edited by Simon Sheppard (17 Dec 2020 01:32)

----------------------------

#3 18 Dec 2020 01:33
RedHut


I think you might be on to something here. It looks like I'm seeing several variations of an issue here with objects being passed on as a string.

Code: Select all

gci $folder |SELECT name,CreationTime,LastWriteTime | ? {$_.CreationTime -gt $_.LastWriteTime}

Name                              CreationTime        LastWriteTime     
----                              ------------        -------------     
20200201-DJI_0902.MP4     10.12.2020 03.50.23 01.02.2020 20.50.48
20200201-DJI_0903.MP4     08.12.2020 13.20.33 01.02.2020 20.55.48
20200201-DJI_0904.MP4     08.12.2020 04.59.37 01.02.2020 21.00.50
I've made a conclusion to go forward with this syntax:

Code: Select all

gci $folder |? {$_.CreationTime -gt $_.LastWriteTime}

Mode                 LastWriteTime         Length Name                                                                                                                                                                                                           
----                 -------------         ------ ----                                                                                                                                                                                                           
-a----        01.02.2020     20.50     3759236792 20200201-DJI_0902.MP4                                                                                                                                                                                 
-a----        01.02.2020     20.55     3759236146 20200201-DJI_0903.MP4                                                                                                                                                                                 
-a----        01.02.2020     21.00     3759234821 20200201-DJI_0904.MP4 
The rest of the options seems unpredictable:

Code: Select all

gci $folder |? CreationTime -gt LastWriteTime

? : The 'Igt' operator failed: Could not compare "12/10/2020 03:50:23" to "LastWriteTime". Error: "Cannot convert value "LastWriteTime" to type "System.DateTime". Error: "The string was not recognized as a valid DateTime. There is an unknown word starting a
t index 0."".
At line:1 char:14
+ gci $folder |? CreationTime -gt LastWriteTime
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (20200201-DJI_0902.MP4:PSObject) [Where-Object], PSInvalidOperationException
    + FullyQualifiedErrorId : OperatorFailed,Microsoft.PowerShell.Commands.WhereObjectCommand

gci $folder |? LastWriteTime -lt CreationTime

? : The 'Ilt' operator failed: Could not compare "02/01/2020 20:50:48" to "CreationTime". Error: "Cannot convert value "CreationTime" to type "System.DateTime". Error: "The string was not recognized as a valid DateTime. There is an unknown word starting at
index 0."".
At line:1 char:14
+ gci $folder |? LastWriteTime -lt CreationTime
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (20200201-DJI_0902.MP4:PSObject) [Where-Object], PSInvalidOperationException
    + FullyQualifiedErrorId : OperatorFailed,Microsoft.PowerShell.Commands.WhereObjectCommand

gci $folder |ft name,LastWriteTime,CreationTime | ? {$_.CreationTime -eq $null}

Name                              LastWriteTime       CreationTime       
----                              -------------       ------------       
20200201-DJI_0902.MP4     01.02.2020 20.50.48 10.12.2020 03.50.23
20200201-DJI_0903.MP4     01.02.2020 20.55.48 08.12.2020 13.20.33
20200201-DJI_0904.MP4     01.02.2020 21.00.50 08.12.2020 04.59.37

gci $folder |ft name,LastWriteTime,CreationTime | ? {$_.LastWriteTime -eq $null}

Name                              LastWriteTime       CreationTime       
----                              -------------       ------------       
20200201-DJI_0902.MP4     01.02.2020 20.50.48 10.12.2020 03.50.23
20200201-DJI_0903.MP4     01.02.2020 20.55.48 08.12.2020 13.20.33
20200201-DJI_0904.MP4     01.02.2020 21.00.50 08.12.2020 04.59.37
----------------------------

#4 18 Dec 2020 11:26
Simon Sheppard


What version of PowerShell are you running?

----------------------------

#5 18 Dec 2020 23:12
RedHut

Code: Select all

$psversiontable
Name Value
---- -----
PSVersion 5.1.19041.610
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.19041.610
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1

----------------------------

#6 19 Dec 2020 14:18
Simon Sheppard


OK version 5.1 should be good for this.

From some googling about this it looks like the short comparison statement will only evaluate a single property, or a single comparison.

If you set a variable $demo equal to some date and then try gci $folder |? CreationTime -gt $demo
it will work.

So it looks like you just need to use Select along with the full script block to get the result you are looking for.