PowerShell File Rotation 8


This PowerShell script is designed for situations where new files are written daily and the type of files might be reports or backups where you don’t need to keep them all, but you want to retain some for a period of time. The files are moved to subdirectories for daily, weekly and monthly. You specify how many daily, weekly or monthly files you want to keep.

#
Function Rotate-Logs {
    <#    

    Public Domain License

    .SYNOPSIS
    Clean up and rotate files

    .DESCRIPTION
    This script rotates files and keeps them in three directories
    \daily
    \weekly
    \monthly

    New files are expected to be written to $LogDir and Rotate-Logs moves them into subdirectories

    .EXAMPLE
    Rotate-Logs -LogDir "c:\MyLogDirectory"

    .LINKS
    http://www.getsurreal.com/powershell/powershell-file-rotation
    #>
    
	Param (
		[Parameter(Mandatory=$True,ValueFromPipeline=$false)]
		[string]$LogDir, # Directory log files are written to
		[Parameter(ValueFromPipeline=$false)]
		[int]$DayOfWeek = 2, # The day of the week to store for weekly files (1 to 7 where 1 is Sunday)
		[Parameter(ValueFromPipeline=$false)]
		[int]$DayOfMonth = 1, # The day of the month to store for monthly files (Max = 28 since varying last day of month not currently handled)
		[Parameter(ValueFromPipeline=$false)]
		[int]$RotationDaily = 7, # The number of daily files to keep
		[Parameter(ValueFromPipeline=$false)]
		[int]$RotationWeekly = 6, # The number of weekly files to keep
		[Parameter(ValueFromPipeline=$false)]
		[int]$RotationMonthly = 5 # The number of monthly files to keep
	)
    
	Process {
		if (-not $LogDir) {
			Write-Host "Error:  -LogDir not set"
			Exit
        }

        $date = Get-Date

        $verify_log_dir = Test-Path $LogDir
        if ($verify_log_dir) {
            $verify_daily_dir = Test-Path "$LogDir\daily"
            $verify_weekly_dir = Test-Path "$LogDir\weekly"
            $verify_monthly_dir = Test-Path "$LogDir\monthly"

            # If the daily directory does not exist try to create it
            if (!$verify_daily_dir) {
                $md_daily = md -Name "daily" -Path $LogDir
                if (!$md_daily){
                    Write-Host "Error setting up log directories. Check Permissions."
                    exit
                }
            }
            # If the weekly directory does not exist try to create it
            if (!$verify_weekly_dir) {
                $md_weekly = md -Name "weekly" -Path $LogDir
                if (!$md_weekly){
                    Write-Host "Error setting up log directories. Check Permissions."
                    exit
                }
            }
            # If the monthly directory does not exist try to create it
            if (!$verify_monthly_dir) {
                $md_monthly = md -Name "monthly" -Path $LogDir
                if (!$md_monthly){
                    Write-Host "Error setting up log directories. Check Permissions."
                    exit
                }
            }
        }
        else {
            Write-Host "Error:  Log directory $LogDir does not exist."
            exit
        }
        
        $logs_root = Get-ChildItem $LogDir | where {$_.Attributes -ne "Directory"}
        
        if ($logs_root) {
            foreach ($file in $logs_root) {
                $file_date = get-date $file.LastWriteTime
                if ($file_date -ge $date.AddDays(-$RotationDaily)) {
                    #Write-Host "$($file.Name) - $($file_date)"
                    Copy-Item "$LogDir\$file" "$LogDir\daily"
                }
                if ($file_date -ge $date.AddDays(-$RotationWeekly*7) -and [int]$file_date.DayOfWeek -eq $DayOfWeek) {
                    #Write-Host "Weekly $($file.Name) - $($file_date)"
                    Copy-Item "$LogDir\$file" "$LogDir\weekly"
                }
                if ($file_date -ge $date.AddDays(-$RotationMonthly*30) -and [int]$file_date.Day -eq $DayOfMonth) {
                    #Write-Host "Monthly $($file.Name) - $($file_date) $([int]$file_date.DayOfWeek)"
                    Copy-Item "$LogDir\$file" "$LogDir\monthly"
                }
                Remove-Item "$LogDir\$file"
            }
            
            $logs_daily = Get-ChildItem "$LogDir\daily" | where {$_.Attributes -ne "Directory"} | Sort-Object LastWriteTime -Descending
            $logs_weekly = Get-ChildItem "$LogDir\weekly" | where {$_.Attributes -ne "Directory"}
            $logs_monthly = Get-ChildItem "$LogDir\monthly" | where {$_.Attributes -ne "Directory"}

            if ($logs_daily) {
                foreach ($file in $logs_daily) {
                    $file_date = get-date $file.LastWriteTime
                    if ($file_date -le $date.AddDays(-$RotationDaily)) {
                        #Write-Host "$file.Name"
                        Remove-Item "$LogDir\daily\$file"                    
                    }
                }
            }

            if ($logs_weekly) {
                foreach ($file in $logs_weekly) {
                    $file_date = get-date $file.LastWriteTime
                    if ($file_date -le $date.AddDays(-$RotationWeekly*7)) {
                        #Write-Host "$file.Name"
                        Remove-Item "$LogDir\weekly\$file"
                    }
                }
            }

            if ($logs_monthly) {
                foreach ($file in $logs_monthly) {
                    $file_date = get-date $file.LastWriteTime
                    if ($file_date -le $date.AddDays(-$RotationMonthly*30)) {
                        #Write-Host "$file.Name"
                        Remove-Item "$LogDir\monthly\$file"
                    }
                }
            }
        }
    }
}
}

Leave a comment

Your email address will not be published.

8 thoughts on “PowerShell File Rotation

  • Alexandr

    Could you please answer why during log rotation files are being copied? Moving them is faster and this does not change file creation date.

  • getSurreal Post author

    Moving the file is a good thought. As is, you’re daily log could get copied to both the weekly and the monthly directory. Of course you could come up with some other logic to handle that allowing you to move the file and keep the original file date.

  • Lemiealu

    I am a bit of a novice to Powershell, I can get the script working by running the following from within the folder the script is in:-
    . .\GFS_Log_Rotation_function.ps1;rotate-logs -logdir E:\Reports

    I am having real trouble getting this to work as a scheduled task though, can anyone explain to me how I can get this to work?

  • Lemiealu

    I worked it out, save the script as a .PSM1 then I created a .PS1 file with the information below, it worked a treat 😀

    Import-Module C:\ocslms\Scripts\GFS_Log_Rotation_function.psm1
    rotate-logs -logdir E:\Reports