Where-Object gives two different results using a equivalent syntax
Posted: 2021-Jul-26, 6:09 pm
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:
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:
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
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.
I've made a conclusion to go forward with this syntax:
The rest of the options seems unpredictable:
----------------------------
#4 18 Dec 2020 11:26
Simon Sheppard
What version of PowerShell are you running?
----------------------------
#5 18 Dec 2020 23:12
RedHut
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.
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
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
----------------------------
#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}
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
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
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
---- -----
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.