37

I'm stumped here on what seems to be a simple problem; so sorry for any bone-headed-ness over here.

I have script that cleans up defunct backup files. After identifying the files I loop over and print out what's being dumped. My problem arises trying to provide feedback/testing when there are zero defunct files. The script looks like...

$Files = Get-ChildItem $BackupPath_Root -include *.bak -recurse 
           | where {$_.CreationTime  -le $DelDate_Backup }  

if ( $Files -eq "" -or $Files.Count  -eq 0 ) {
    write-host "   no files to delete."    #<-- this doesn't print when no files
} else {
   foreach ($File in $Files) {
      write-host “$File” 
      Remove-Item $File | out-null
   } 
}

The if checking for no files doesn't catch the no file condition. What is the appropriate way to test $Files for no results ?

EBarr
  • 11,826
  • 7
  • 63
  • 85

5 Answers5

63

Try wrapping in @(..). It creates always an array:

$Files = @(Get-ChildItem $BackupPath_Root -include *.bak -recurse 
           | where {$_.CreationTime  -le $DelDate_Backup })
if ($Files.length -eq 0) {
  write-host "   no files to delete." 
} else {
  ..
}
stej
  • 28,745
  • 11
  • 71
  • 104
  • 2
    This is a great trick for quirky PowerShell array handling/interpretation. Thanks! – Eric Nicholson Jul 28 '11 at 15:41
  • Upped since this is in my opinion the right (and easy) way to handle arrays that might be null or where the following pipeline will fail if it is null. – CosmosKey Jul 28 '11 at 23:32
17

When there are no files, $Files is equal to $null, so as EBGreen suggests you should test against $null. Also, $Files.Count is only useful when the result is a collection of files. If the result is a scalar (one object) it won't have a count property and the comparison fails.

Performance tip: when you need to search for just one extension type, use the -Filter parameter (instead of -Include) as it's filtering on the provider level.

Shay Levy
  • 121,444
  • 32
  • 184
  • 206
  • 1
    +1 for the filter tip, but i simplified my example and filter doesn't seem to work for multiple extension (*.bak and *.tran) the way include does :-( – EBarr Jul 29 '11 at 14:56
  • I have to doubt this answer as `if ($Files=$null)` does not return true but `if (!$Files)` does. – Marc Sep 26 '16 at 11:52
  • Sorry, apparently you can test `if ($Files -eq $null)` or `if (!$Files)` but not, for some reason, `if ($Files = $null)`. – Marc Sep 26 '16 at 12:37
10

The variable evaluates to a null-valued expression when scanned folder is empty. You can use:

if (!$Files) {
# ...
}
Emiliano Poggi
  • 24,390
  • 8
  • 55
  • 67
4

Try testing for $files -eq $null also.

EBGreen
  • 36,735
  • 12
  • 65
  • 85
2

Specifying the [bool] type in front of a get-childitem command will return True if anything is found, or false if nothing is found. This is what Emiliano's answer is doing, but without the negative requirement. You can make either work but I prefer [bool] with some of the more complex conditional statements just to make it easier to follow.

[bool](Get-ChildItem C:\foo.txt)

Used in an If statement

if ([bool](Get-ChildItem C:\foo.txt)) {write-output "foo.txt exists"}
Robert Overmyer
  • 182
  • 1
  • 1
  • 8