PowerShell script to zip files inside many folders recursive - powershell

I would like to go inside every folder recursive in some location,
for example: C:\Logs and zip files to the same folder.
I need to skip every .zip file. I don't know how to make my script to do this:
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:\Logs'
$now = Get-Date -Hour 0 -Minute 00 -Second 00
$days = 5
$lastWrite = $now.AddDays(-$days)
Get-ChildItem $targetFolder -Recurse -Exclude *zip* | Where-Object { $_ -is [System.IO.FileInfo] } | ForEach-Object {
If ($_.LastWriteTime -lt $lastWrite)
{
$_ | New-Zip $($targetFolder + $_.Name + ".zip" )
$_ | Add-Zip $($targetFolder + $_.Name + ".zip" )
}
}

You are currently excluding any file or folder that contains the phrase 'zip' in its name as you have a wildcard either side of it:
Get-ChildItem $targetFolder -Recurse -Exclude *zip*
To exclude zip files you just need to update your Exclude statement so that it matches only the zip file extension:
Get-ChildItem $targetFolder -Recurse -Exclude *.zip

Related

How to use the COM Object Method to rename the item in compressed/zip file

How do I rename the file inside the compressed file?
$timestamp = (Get-Date).AddMonths(-1).ToString('yyyy-MM')
$newFolderTimeStamp = (Get-Date).AddMonths(-1).ToString('MM - MMM-yyyy')
$sourceFile = "D:\Testing\1.txt","D:\Testing\2.txt","D:\Testing\3.txt","D:\Testing\4.txt","D:\Testing\5.txt"
#$sharedrive = "\\fs2\Backups\it\users.xlsx"
$newFolder = "D:\Testing\bin\$newFolderTimeStamp.zip"
######Compressed File
function Add-Zip
{
param([string]$zipfilename)
if(-NOT (test-path($zipfilename)))
{
#create an empty zip file
set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
#make sure it is not set to ReadOnly
(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
}
}
######Get file for today's date
Get-ChildItem $sourceFile -Force | Where-Object{$_.LastWriteTime -gt $date -and $_.extension -ne ".zip"} | add-Zip $newFolder
Tried , but only rename the zip file name.
Get-ChildItem $sourceFile -Force | Rename-Item -NewName {$_.Basename + '_' + $timestamp + $_.Extension } | Where-Object{$_.LastWriteTime -gt $date -and $_.extension -ne ".zip"} | add-Zip $newFolder
Expected result
06 - Jun-2019.zip
1_2019-06.txt
2_2019-06.txt
3_2019-06.txt
4_2019-06.txt
5_2019-06.txt

Unable to get filename using Get-ChildItem with PowerShell

I am checking each folder for an HTMLreports directory and then deleting files that are over 30 days old. But when it gets to the filename for $document.Name or $image.name in the foreach loop it is not getting the filename to delete the file for the Remove-Item command.
$items = Get-ChildItem -Path "C:\Program Files (x86)\Jenkins\jobs\"
$time = (Get-Date).AddDays(-30)
$today = Get-Date
echo $today
# enumerate the items array
foreach ($item in $items) {
# if the item is a directory, then process it.
if ($item.Attributes -eq "Directory") {
Write-Host "job folder: " $item.Name
$folder = Get-ChildItem -Path ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\")
if (Test-Path ("C:\Program Files (x86)\Jenkins\jobs\"+$item.Name+"\htmlreports\")) {
$reports = Get-ChildItem -Path ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\")
foreach ($report in $reports) {
Write-Host "report folder" $report.Name
$documents = Get-ChildItem -Path ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\" + $report.Name + "\") |
Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $time }
foreach ($document in $documents) {
if ($document.Attributes -eq "Directory") {
echo "Folder exists"
Write-Host "delete document folder" $document.Name
Remove-Item ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\"+$report.Name+"\" + $document.Name)
} else {
echo "File exists"
Write-Host "delete document " $document.Name
Remove-Item ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\"+$report.Name+"\" + $document.Name)
}
}
if (Test-Path ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\" + $report.Name + "\images\")) {
echo "Image Folder exists"
$images = Get-ChildItem -Path ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\" + $report.Name + "\images\") -Name |
Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $time }
foreach ($image in $images) {
Write-Host "delete image: C:\Program Files (x86)\Jenkins\jobs\"$item.Name"\htmlreports\"$report.Name"\images\"$image.Name
Remove-Item ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\" + $report.Name + "\images \" + $image.Name);
}
}
}
}
}
}
Instead of repeating a long path over and over again, store it in a variable.
You erroneously have an additional space inserted several times between
C:\Program Files (x86)\Jenkins\jobs\
and also
"C:\Program Files (x86)\Jenkins\jobs\"
Previous answer removed after looking at this again.
You just seem to be wanting to remove all the files after a specific date in the jobs\htmlreport folder and it's images subfolder you can reduce your code to this...
Clear-Host
$ReportFiles = (Get-ChildItem -Path "${env:ProgramFiles(x86)}\Jenkins\jobs\htmlreports" -Recurse).FullName
($today = Get-Date)
($time = (Get-Date).AddDays(-30))
ForEach($File in (Get-ChildItem -Path $ReportFiles -File))
{
If ($File.FullName.CreationTime -lt $time)
{"Processing $($File.FullName)"}
}
… of course if there are other folders, you should just filter for those two.
Thank You everyone for all your insights, I was able to get this working with my below code. I am checking all the folders or reports in the jobs directory and for each report I am going into the htmlreports directory and deleting all files and images in the images directory that are more than 30 days old. If there is a cleaner way to do this please let me know, I am using powershell v1.0.
$items = gci "C:\Program Files (x86)\Jenkins\jobs\"
($today = Get-Date)
($time = $today.AddDays(-30))
Write-Host $today
# enumerate the items array
foreach ($item in $items) {
# if the item is a directory, then process it.
if ($item.Attributes -eq "Directory") {
Write-Host "job folder: " $item.Name
if (Test-Path ("C:\Program Files (x86)\Jenkins\jobs\"+$item.Name+"\htmlreports\")) {
$reports = Get-ChildItem -Path ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\")
foreach ($report in $reports) {
Write-Host "report folder" $report.Name
$documents = ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\" + $report.Name + "\")
dir -recurse $documents | where {$_.LastWriteTime -le $time} | del
if (Test-Path ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\" + $report.Name + "\images\")) {
Write-Host "Image Folder exists"
$images = ("C:\Program Files (x86)\Jenkins\jobs\" + $item.Name + "\htmlreports\" + $report.Name + "\images\")
dir -recurse $images | where {$_.LastWriteTime -le $time} | del
}
}
}
}
}

Powershell Compress-Archive files into folders

How can I place the result into folders in the archive?
for example:
$Compress-Archive -Path .\Client\*.exe, .\Server\*.exe -DestinationPath ('Build_' + (get-date -Format yyyy.MM.dd) + '.zip')
I would like to have a folder Client with it's exe files and a folder Server with it's exe files in the archive. Now all files are directly in the 'root' of the archive.
When compressing an entire folder the folder name is included in the archive.
Something like this may get you started modified from here :-
https://social.technet.microsoft.com/Forums/en-US/fb835e63-0ed5-417b-980b-46d2982f4e0b/add-a-folder-to-an-existing-zip-file-using-powershell-v4-or-lower?forum=winserverpowershell
$sources = "c:\client","c:\server"
$destination = "c:\test\" + "multifoler.zip"
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
}
}
foreach($source in $sources){
Get-Item $source | Add-Zip $destination
}

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
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++
}
}

How to zip folders using powershell

I run a program in windows powershell which lists name of files which have been modified before 30 days. I need to compress these files in a zip format. What should be the code?
#List all the folders in G:\logfiles
$folders = (Get-ChildItem -Path "G:\logfiles" | Where-Object {$_.Attributes -eq "Directory"} | Select Fullname)
#looping all folders
Foreach ($folder in $folders)
{
$files = Get-ChildItem G:\logfiles\$folder | Where{$_.LastWriteTime -lt (Get-Date).AddDays(-30)
}
Foreach ($file in $files)
{
Move-Item $file G:\logfiles\$folder\$N # *To move files to a folder name $N*
}
I will refer you to powershell 5.0 and the new Compress-Archive cmdlet
Compress-Archive -DestinationPath $folderToZip
With the down function you can compress your files.
function zipFile($Source ,$DestZip ){
$folder = Get-Item -Path $Source
$ZipFileName = $DestZip + ".zip"
set-content $ZipFileName ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
# Wait for the zip file to be created.
while (!(Test-Path -PathType leaf -Path $ZipFileName))
{
Start-Sleep -Milliseconds 20
}
$ZipFile = (new-object -com shell.application).NameSpace($ZipFileName)
#BACKUP - COPY
$ZipFile.CopyHere($Source)
Write-Host "#Created zip file :" $DestZip
}