Tuesday, January 29, 2013

Archive files monthly using PowerShell

Problem

My systems creates close 100.000 files every monthly. These files are related to integration or logs and contains only text. After some months the file system will contain more than 1 million files, and also take off quite much storage.

I used Google to get inspiration to create a script to archive they in a structured way. I could probably delete the files, but I want to keep them for some time - in case I need to.

If found some scripts, but none of the did the trick - so I created one myself using PowerShell. The scripts creates and _old folder beneath the folder and archive all files (except .ZIP files) monthly.

The scripts utilitize 7-zip to archive the files.

Solution

<# 
.SYNOPSIS 
   ZIP old files by monthly .ZIP files
.DESCRIPTION
   Creates a .ZIP files in a old\ folder containing files per monthly which is older than first day of the previous month
.NOTES 
   Version: 1.0
   Author : Henrik Næss
#> 

$zipPath = "C:\Program Files (x86)\PortableApps\7-ZipPortable\App\7-Zip64\7z.exe"
$archivemonths = 1

$tempFolder = gc env:temp 
$cutoffdate = (Get-Date -Hour 0 -Minute 0 -Second 0 -Day 1).AddMonths(-$archivemonths)

Function ArchiveFilesByMonth
{
  param(
    [Parameter(Mandatory=$true)][string] $archivefolder,  
    [Parameter(Mandatory=$true)][string] $includePattern
    )

  if(!(Test-Path $archiveFolder))
  {
    Write-Host "Folder $($archiveFolder) doesn't exists"
    return
  }
  Set-Location $archivefolder
  
  $oldFolder = Join-Path $archivefolder "_old\"
  if(!(Test-Path $archiveFolder)) { New-Item $oldFolder -itemtype directory }

  $randomNo = Get-Random
  $filelist = $tempFolder + "filelist$($randomNo).txt"
  $myarray=@()

  gci $archivefolder -recurse -include $includePattern -exclude *.zip | ?{$_.LastWriteTime -lt $cutoffdate} | %{
    #record the month & year of the files in an array
    $temp='' | Select Filenamex, Period
    $temp.Filenamex = ($_ | Resolve-Path -Relative).TrimStart(".\")
    $temp.Period = '{0:MMyyyy}' -f $_.LastWriteTime
    $myarray += $temp
  }
  
  #Get each unique month/year from the array
  foreach($period in ($myarray | Select Period -unique)){
    $zipFileYYYYmm = $oldFolder + ($period.Period).Substring(2, 4) + ($period.Period).Substring(0, 2) + ".zip"
    
    $myarray | ?{$_.Period -eq $period.period} | Select -expand Filenamex | out-file $filelist -encoding ASCII
    $argumentlist = "a -tzip $($zipFileYYYYmm) @$($filelist)"
    
    $result = start-process "$($zipPath)" -argumentlist $argumentlist -NoNewWindow -wait
    
    # If .ZIP created then delete the files
    # can later be changed to move "if using 7-Zip 9.22 beta or later"
    if(Test-Path $zipFileYYYYmm) { gc $filelist | %{gci $_} | %{$_.Delete() } }
  }
  Write-Host "Completed $($archivefolder)"
}

Function ArchivePart1
{
  # exampes
  ArchiveFilesByMonth ("C:\MyFiles\ARCHIVE") AP*
  ArchiveFilesByMonth ("C:\MyFiles\LOGS") AP*
}

ArchivePart1

No comments:

Post a Comment