I use a PowerShell command to count ZIP files modified within the past 30-ish days, that goes something like this:

(gci "\\servername\sharename\foldername\subfoldername\*.zip" | where {$_.LastWriteTime -gt ((get-date)-(new-timespan -day 35))}).count

However, my true intention with this script is to get a count of files modified within the previous calendar month. Obviously, this script has a couple weaknesses.

  • Whenever I run the script, I have to calculate the days between now and the beginning of the previous month and then edit the script accordingly.
    • I recognize that I might have to edit the script every time anyway, but having to count days instead of just specifying a month is a little irksome.
  • The script will also catch any files modified within the current month.

Is there a way I can modify this command so that it only selects files modified within a specific month, or is this just a limitation of PowerShell?

If the script can be made to target a specific month, can it then also be written to auto-target the previous month so I don't have to modify it every time?

EDIT: Much thanks to zdan for the help here, and also to Google for walking me through some other issues. I figured I'd post my full, final script here in case anyone was interested.

This script counts ZIP files in the target directory which were modified within the previous month. The IF/ELSE statement early on helps account for cases where the current month is January. This script also depends on a file called Targets.txt, in the current working folder, in which one or multiple target systems may be listed (one machine name or IP per line). The script gracefully handles and logs errors if a target system or folder is unreachable, and all results are output to a text file (dated with the target month/year) in the current working folder. I've also made adjustments for compatibility with PowerShell versions before 3, where (gci).count would return nothing when the value should be zero or one. (Solved in this question.)

$ErrorActionPreference = 'Stop'
if ((get-date).Month -eq 1)
    $TargetMonth = 12
    $TargetYear = (get-date).Year-1
    $TargetMonth = (get-date).Month-1
    $TargetYear = (get-date).Year
echo "ZIP file counts for $TargetMonth/$TargetYear" | Out-File "$TargetMonth-$TargetYear ZIPs.txt"
echo "----------------------------------" | Out-File "$TargetMonth-$TargetYear ZIPs.txt" -Append
echo "`n" | Out-File "$TargetMonth-$TargetYear ZIPs.txt" -Append
foreach ($Target in gc 'Targets.txt')
        $ThisTarget = @(gci "\\$Target\c$\Folder\Subfolder\ZIPs\*.zip" | where {($_.LastWriteTime.Month -eq $TargetMonth) -and ($_.LastWriteTime.Year -eq $TargetYear)}).count
        $ZIPTotal += $ThisTarget
        echo "$Target has $ThisTarget ZIPs." | Out-File "$TargetMonth-$TargetYear ZIPs.txt" -Append
        echo "$Target could not be reached or ZIPs directory not found." | Out-File "$TargetMonth-$TargetYear ZIPs.txt" -Append
        $ZIPsErrors ++
echo "----------------------------------" | Out-File "$TargetMonth-$TargetYear ZIPs.txt" -Append
echo "`n" | Out-File "$TargetMonth-$TargetYear ZIPs.txt" -Append
echo "The total number of ZIPs counted is $ZIPsTotal" | Out-File "$TargetMonth-$TargetYear ZIPs.txt" -Append
echo "Total number of errors encountered is $ZIPsErrors" | Out-File "$TargetMonth-$TargetYear ZIPs.txt" -Append
rv TargetMonth
rv TargetYear
rv Target
rv ThisTarget
rv ZIPsTotal
rv ZIPsErrors
$ErrorActionPreference = 'Continue'

The beauty of powershell is that you get full-blown .NET objects that you can inspect. In the case of dates, powershell uses the DateTime class which exposes Month and Year properties that you can take advantage of:

(gci "\\servername\sharename\foldername\subfoldername\*.zip" | 
    ?{ $lwt = $_.LastWriteTime; ($lwt.Month -eq ((get-date).Month-1)) -and (($lwt.Year -eq (Get-Date).Year))}).count

Important: The above will not work if you run it in January. You'll need to adjust the year and month accordingly when that happens.

  • Is ? an alias for where that I'm forgetting? – Iszi May 3 '13 at 20:05
  • @Iszi Yes it is. – zdan May 3 '13 at 21:30
  • Reviewing this, I'm trying to simplify it just a bit. Is $lwt = $_.LastWriteTime; really necessary, or could I remove that and just insert $_.LastWriteTime in place of $lwt everywhere else? – Iszi Aug 8 '13 at 18:19
  • @Iszi yes you can, it's just up to personal preference. – zdan Aug 8 '13 at 18:22
  • This is strange. For instances where the count should be 1, I get a blank output. Other cases seem to work fine. Thoughts? – Iszi Aug 8 '13 at 19:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.