valdroni
valdroni

Reputation: 168

Powershell to zip folder & files, then delete old files

I want to use Powershell to automate the: 1. compression of log files (.xml and .dat extensions) older than 7 days, 2. copy these compressed archives elsewhere and 3. then delete the raw log files from source.

I am using the following Powershell script which I pieced together from various resources.

function New-Zip
  {
   param([string]$zipfilename)
    set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
    (dir $zipfilename).IsReadOnly = $false
  }

function Add-Zip
  {
   param([string]$zipfilename)

   if(-not (test-path($zipfilename)))
    {
    set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
    (dir $zipfilename).IsReadOnly = $false  
    }

  $shellApplication = new-object -com shell.application
  $zipPackage = $shellApplication.NameSpace($zipfilename)

   foreach($file in $input) 
     { 
        $zipPackage.CopyHere($file.FullName)
        Start-sleep -milliseconds 500
     }
   }

$targetFolder = 'C:\source'
$destinationFolder = 'D:\destination\'
$now = Get-Date
$days = 7
$lastWrite = $now.AddDays(-$days)

Get-ChildItem $targetFolder -Recurse | Where-Object { $_ -is [System.IO.FileInfo] } | ForEach-Object {
If ($_.LastWriteTime -lt $lastWrite)
{
    $_ | New-Zip $($destinationFolder + $_.BaseName + ".zip") 
    $_ | Add-Zip $($destinationFolder + $_.BaseName + ".zip")
}
}

Get-ChildItem $targetFolder -Recurse -Include "*.dat", "*.xml" | WHERE {($_.CreationTime -le $(Get-Date).AddDays(-$days))} | Remove-Item -Force

This script does work reasonably well, as it archives only the files, and copies them on destination folder.

If I have a structure of C:\source\bigfolder\logfile.dat, the resulting zip file will not get the folder structure as I would like:

logfile.zip>bigfolder>logfile.dat

Instead, it just gets: logfile.zip>logfile.dat

Can someone help in figuring this out ?

To fine tune it even better, I would like if possible to build some logic, so the files are compressed only when a specific criteria is met.

The raw log files that I compress have a naming routine as following:

Folders: 
  emstg#12_list\randomstring.xml

Individual log files:
  emstg#12_query_data.xml
  emstg#12_events_cache.dat etc... 

As you may see the start of these files is same with emstg#number.

How to implement a "name-detection" mechanism in script above ?

Thanks

Upvotes: 3

Views: 10479

Answers (1)

Bum
Bum

Reputation: 99

you could zip a folder by using [System.IO.Compression] I wrote this based on your script. My idea is to copy the whole folder structure of the file you need to compress into a temp folder and then zip that temp folder. For the name-detection, you just need another where-object (modify the code as you want)

function Zip
  {
    param(
        [string]$source,
        [string]$des
    )
    add-type -AssemblyName System.IO.Compression.FileSystem
    [System.IO.Compression.ZipFile]::CreateFromDirectory($source,$des,'Optimal',$true)
    Start-sleep -s 1
}


$targetFolder = "C:\source"
$destinationFolder = "C:\destination"
$temp = "C:\temp"
$now = Get-Date
$days = 7
$lastWrite = $now.AddDays(-$days)
$i = 1

Get-ChildItem $targetFolder -Recurse | Where-Object { $_ -is [System.IO.FileInfo] } | Where-Object {$_ -like "*.*"} | ForEach-Object {
    If ($_.LastWriteTime -lt $lastWrite) {
        $halfDir = $_.DirectoryName.Trim($targetFolder)
        $s = $temp + "\" + $i + "\" + $halfDir
        $d = $destinationFolder + "\" + $_.BaseName + ".zip"
        Copy-Item $_.DirectoryName -Destination $s
        Copy-Item $_.FullName -Destination $s
        Zip -source $s -des $d
        $i++
    }
}

Upvotes: 1

Related Questions