How can I write a script to count files modified within a particular month?
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
}
else
{
$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')
{
try
{
$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
}
catch
{
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'
Solution 1:
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.