The code below zips the following files:
c:\test\1.txt
c:\test\2.txt
c:\test\3.txt
into test.zip like:
1.txt
2.txt
3.txt
but what I would like is to include the directory test:
test\1.txt
test\2.txt
test\3.txt
Any idea on how to do this?
$zipFilename = 'c:\test.zip'
$zipDir = 'c:\test'
Set-Content $zipFilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
$shell = New-Object -ComObject Shell.Application
$zipPackage = $shell.NameSpace($zipFilename)
Get-ChildItem $zipDir -Recurse | foreach {
# echo $_.FullName
$zipPackage.CopyHere($_.FullName)
Start-Sleep -Milliseconds 1000
}
Do you have a reason to loop through the files?
You could just skip the loop and outright zip the files/folder structure
$zipFilename = 'c:\test.zip'
$zipDir = 'c:\test'
Set-Content $zipFilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
$shell = New-Object -ComObject Shell.Application
$zipPackage = $shell.NameSpace($zipFilename)
$zipPackage.CopyHere($zipDir)
If you have additional processing you could add a dynamic sleep. Wait a second per file.
Sleep (Get-childitem $zipDir -recurse | Measure-Object | Select-Object -expandproperty Count)
Related
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
}
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
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++
}
}
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
}
I'm using the following function to add files to a .zip archive which works fine, but I need to be able to include the parent directory for some of the files. Any ideas?
function Add-ZipFile
{
param([string]$zipfilename,
[string]$filter)
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)
$files = get-childitem -Filter "$filter" -recurse
foreach($file in $files)
{
$zipPackage.CopyHere($file.FullName)
Start-sleep -milliseconds 500
}
}
Based on my knowledge you cannot add to a zip file one specific file using shell.application and saving its folder structure.
You have two choice:
Add single files in a flat structure as your script do
Add one folder and all its content ( this save the structure folder
using the folder added as a parent folder):
$Directory = Get-Item .
$ParentDirectory = Get-Item ..
$ZipFileName = $ParentDirectory.FullName + $Directory.Name + ".zip"
if (test-path $ZipFileName) {
echo "Zip file already exists at $ZipFileName"
return
}
set-content $ZipFileName ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
(dir $ZipFileName).IsReadOnly = $false
$ZipFile = (new-object -com shell.application).NameSpace($ZipFileName)
$ZipFile.CopyHere($Directory.FullName)
I suggest, as in my comment to your question, to use a safer way to create zip files programmatically as DotNetZip do (IMO).
Ended up using CSharpZipLib. Worked as I'd hoped.
Thanks everyone.