Search code examples
powershellarchive

Powershell Script to clean up logs on a Monthly Basis


Powershell newbie here again with another question.

We currently have a log folder accumulating text files. My supervisor would like for me to create a script where only the current month's logs are visible. All previous months should be moved to an archive folder. He would like for me to create a powershell script we can run once a month to achieve this.

For example, our log folder should only have logs from January 2021. Anything older than January 2021 should be archived. Once February 1, 2021 hits, all the logs from January 2021 should be moved to the archive folder, and so on.

How can I achieve a script that looks at the folder and only keeps the logs for the current month? Any guidance, resources, videos, etc are greatly appreciated! I've been scouring the internet for resources, but I haven't quite found anything that suits my needs.

Update: Was able to find a wonderful script here: PowerShell: Sort and Move Files by Date to month and year provided by Thomas Maurer (all credit to him!)

# Get the files which should be moved, without folders
$files = Get-ChildItem 'C:\Users\testuser\Desktop\log' -Recurse | where {!$_.PsIsContainer}
 
# List Files which will be moved
$files
 
# Target Filder where files should be moved to. The script will automatically create a folder for the year and month.
$targetPath = 'C:\Users\testuser\Desktop\log\archive'
 
foreach ($file in $files)
{
# Get year and Month of the file
# I used LastWriteTime since this are synced files and the creation day will be the date when it was synced
$year = $file.LastWriteTime.Year.ToString()
$month = $file.LastWriteTime.Month.ToString()
 
# Out FileName, year and month
$file.Name
$year
$month
 
# Set Directory Path
$Directory = $targetPath + "\" + $year + "\" + $month
# Create directory if it doesn't exsist
if (!(Test-Path $Directory))
{
New-Item $directory -type directory
}
 
# Move File to new location
$file | Move-Item -Destination $Directory
}

What I would like to achieve now: This script works great, but I am trying to tinker with it so I can move everything EXCEPT the current month. I'm still researching and investigating, so I will make sure to update my post if I am able to figure out this missing piece for me. Thank you all for your help!


Solution

  • One approach to leave the files that were last modified in this month is to use a small helper function that formats the LastWriteTime date into a string yyyy\MM.

    function Format-YearMonth ([datetime]$date) {
        # simply output a string like "2021\01"
        return '{0:yyyy\\MM}' -f $date
    }
    
    $sourcePath = 'C:\Users\testuser\Desktop\log'
    $targetPath = 'C:\Users\testuser\Desktop\log\archive'
    $thisMonth  = Format-YearMonth (Get-Date)
    
    # Get the files which should be moved, without folders 
    # this can be more efficient if all files have the same extension on which
    # you can use -Filter '*.log' for instance.
    Get-ChildItem -Path $sourcePath -File -Recurse | 
        # filter out the files that have a LastWriteTime for this year and month
        Where-Object {(Format-YearMonth $_.LastWriteTime) -ne $thisMonth } |
        ForEach-Object {
            # Set destination Path
            $Directory = Join-Path -Path $targetPath -ChildPath (Format-YearMonth $_.LastWriteTime)
            # Create directory if it doesn't exsist
            if (!(Test-Path $Directory)) {
                $null = New-Item $Directory -type Directory
            }
            Write-Host "Moving file '$($_.FullName)' to '$Directory'"
            # Move File to new location
            $_ | Move-Item -Destination $Directory -Force
        }