6

Why is the code below returning $null? I'm trying to store just unique values.

$DailyPathsToDelete = @("C:\temp\IMG000483\","C:\temp\IMG000483\")
$DailyPathsToDelete = Select-Object $DailyPathsToDelete -Unique 

3 Answers 3

15

Short answer:

To get all unique paths, you should pipe $DailyPathsToDelete to Select-Object and set the Unique switch.

$DailyPathsToDelete = $DailyPathsToDelete | Select-Object -Unique

Longer answer:

1. Why it's not working

After running your script $DailyPathsToDelete equals $null because (in the second line of your script) $DailyPathsToDelete is bound to the parameter Property. The parameter InputObject of the Select-Object cmdlet was not speficified, which is why the result of the invocation of Select-Object is $null.

This can be easily verified by tracing your expression:

Trace-Command -psHost -Name ParameterBinding { Select-Object $DailyPathsToDelete -Unique}

gives:

DEBUG: ParameterBinding Information: 0 : BIND NAMED cmd line args [Select-Object]
DEBUG: ParameterBinding Information: 0 :     BIND arg [True] to parameter [Unique]
DEBUG: ParameterBinding Information: 0 :         COERCE arg to     [System.Management.Automation.SwitchParameter]
DEBUG: ParameterBinding Information: 0 :             Parameter and arg types the same, no coercion is needed.
DEBUG: ParameterBinding Information: 0 :         BIND arg [True] to param [Unique]     SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : BIND POSITIONAL cmd line args [Select-Object]
DEBUG: ParameterBinding Information: 0 :     BIND arg [System.Object[]] to parameter [Property]
DEBUG: ParameterBinding Information: 0 :         BIND arg [System.Object[]] to param [Property] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Select-Object]
DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing
DEBUG: ParameterBinding Information: 0 : CALLING EndProcessing

2. How to fix it

Using Select-Object:

$DailyPathsToDelete = $DailyPathsToDelete | Select-Object -Unique

Using Sort-Object:

$DailyPathsToDelete = $DailyPathsToDelete | Sort-Object -Unique

3. How NOT to fix it

I would advise against using Get-Unique in your scenario since Windows local file systems (NTFS, FAT and variants) are case insensitive.

Example:

$DailyPathsToDelete = @("C:\temp\IMG000483\","C:\Temp\IMG000483\")
PS C:\> $DailyPathsToDelete | get-unique
C:\temp\IMG000483\
C:\Temp\IMG000483\
Sign up to request clarification or add additional context in comments.

Comments

5

You can try :

$unique = $DailyPathsToDelete | Get-Unique

Comments

5
  1. With Get-Unique, gotcha - Get-Unique is case-sensitive and you also have to sort the list first!

    $DailyPathsToDelete = $DailyPathsToDelete | Sort-Object | Get-Unique

  2. With Select-Object

    $DailyPathsToDelete = $DailyPathsToDelete | Select-Object -Unique

  3. With Sort-Object

    $DailyPathsToDelete = $DailyPathsToDelete | Sort-Object -Unique

3 Comments

Actually, Select-Object is also case-sensitive. Example: "temp","Temp" | select -unique returns two items, not one.
Also, with Get-Unique one must use the -CaseSensitive parameter to Sort-Object: try this -- "abc", "Abc", "def", "abc" | sort -Case | Get-Unique -- with and without it and you get different results!
@msorens You're absolutely right. Funny, I actually reported this behavior to the PowerShell team in 2011 and now it's now added to the help topics.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.