As promised in my previous post, here is the script that our group developed during Singapore PowerShell Saturday #008 event.
This script relies on System.IO.Compression.FileSystem assembly to read the contents of ZIP(archive) for without extracting them to the disk. The advantage with this script is, it will not consume any resources/disk space because it is directly reading the zip file contents without extraction.
This script can take multiple ZIP files as input and return the output in PSObject format. This format is helpful if you want to feed the output of this script to some other script/function/cmdlets. It also supports exporting the output to CSV easily with the –ExportCSVFileName parameter. You need to give the CSV file path where you want to store it.
Note that this script works only if you have Dotnet Framework 4.5 or above. This is because the ZipFile class used to read the zip contents is made available starting from dotnet framework v4.5. I will share you other script in my next article which can be used without any dependency on dotnet version. But the only downside I noticed so far is, we can not determine what is the compressed file size and what is the uncompressed file size.
Code
[cmdletbinding()] param( [Parameter(Mandatory=$true)] [string[]]$FileName, [String]$ExportCSVFileName ) #Exit if the shell is using lower version of dotnet $dotnetversion = [Environment]::Version if(!($dotnetversion.Major -ge 4 -and $dotnetversion.Build -ge 30319)) { write-error "You are not having Microsoft DotNet Framework 4.5 installed. Script exiting" exit(1) } # Import dotnet libraries [Void][Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') $ObjArray = @() foreach($zipfile in $FileName) { if(Test-Path $ZipFile) { $RawFiles = [IO.Compression.ZipFile]::OpenRead($zipFile).Entries foreach($RawFile in $RawFiles) { $object = New-Object -TypeName PSObject $Object | Add-Member -MemberType NoteProperty -Name FileName -Value $RawFile.Name $Object | Add-Member -MemberType NoteProperty -Name FullPath -Value $RawFile.FullName $Object | Add-Member -MemberType NoteProperty -Name CompressedLengthInKB -Value ($RawFile.CompressedLength/1KB).Tostring("00") $Object | Add-Member -MemberType NoteProperty -Name UnCompressedLengthInKB -Value ($RawFile.Length/1KB).Tostring("00") $Object | Add-Member -MemberType NoteProperty -Name FileExtn -Value ([System.IO.Path]::GetExtension($RawFile.FullName)) $Object | Add-Member -MemberType NoteProperty -Name ZipFileName -Value $zipfile $ObjArray += $Object if(!$ExportCSVFileName) { $Object } } } else { Write-Warning "$ZipFileInput File path not found" } if ($ExportCSVFileName){ try { $ObjArray | Export-CSV -Path $ExportCSVFileName -NotypeInformation } catch { Write-Error "Failed to export the output to CSV. Details : $_" } } }
Most of the code is self-explanatory. If you get any questions about this, please feel free to raise them. I am more than happy to help you.
Usage:
Output
Hope this helps and Happy learning…
Comments on this entry are closed.
Thanks! This worked for me perfectly! am using it to actually search for a files within thousands of zip files…
Glad to know that it helped
I am trying to use this script. How many zip filenames do i need to put in for it to display what is in them? i am not really familiar with powershell, so I am attempting to figure this out.
Hi, You can input any number of zip files as argument. You can start with one zip file to understand the usage. See the screenshot in the post for better understanding.
This looks great however I need to search a director file with zip files for a string. Thoughts?
Can you give an example?
My example here looks like this:
Note: Folder Stucture (.cst files are really .zip files)
\\Customers\Customer1\Customer1.zip\Customer1.cst
\\Customers\Customer1\Customer1.zip\Customer1.xmls
\\Customers\Customer2\Customer2.zip\Customer2.cst
\\Customers\Customer2\Customer2.docx
\\Customers\Customer3\Customer3.zip\Customer3.cst
\\Customers\Customer3\Customer3\Customer3.rtf
What would I need to do to get your script updated to look inside the Customers directory, for all files where ‘simulate=true’ and send all file names and directory paths to a log file?
Let me know what you think and awesome script.
Great script and many thanks for doing it quick question what if i want to compare 2 zip files without extracting them and producing differences in txt file any thought on this.
nice one! how can I use this to read an XML file inside a zip?
“PowerShell 3” required for successful execution of this program.
If you google for “powershell 2 .net 4” etc., there’s a couple of things to do (a couple of simple registry entries; powershell_exe.config file, etc) to get Powershell 2 to use/see the .Net 4.0+ library. Find and do those. You have installed .Net 4.0/4.5 framework or higher first (duh), right?
…and the above script worked just fine for me w/o mods.
Windows 7, Powershell 2.0, .Net framework v 4.5+ – my work computer…
Of course, Powershell ISE 3.0 >> Powershell 2.0, so just install Powershell 3.0 or higher if you can…
or use command-line zip tools, like 7zip, info-zip, or (*barf* winzip command line tools) instead.
Yes you need .net4.5
This seems great. How do I use this script? Do I copy paste and save it to a specific place? I am new to powershell and would appreciate a little guidance
Val, Copy the code to a file and name it as Get-zipfilecontent.ps1 and execute it by passing the zip file names as shown in the screenshots.
Hello. The article refers to a script that is not dependent on a particular dotnet version. Has that script been posted yet? I can’t seem to locate it on this site. Thx.
Mar, yoiu can try the solution from http://www.howtogeek.com/tips/how-to-extract-zip-files-using-powershell/. It doesn’t depend on a dotnet version.
Hello,
Thanks for this page and sharing your script. I applied this script to read zip files containing evtx log files and then I tried to use Get-WinEvent to find a specific event but it seems not to be working. Command I tried was this one. I used Get-Member and it’s not reporting any properties?
.\Get-ZipFileArchive.ps1 -FileName G:\Event-Log-Archive\ServerName\ServerName_08-10-2016_Security.zip | Get-WinEvent -FilterHashTable @{LogName=”Security”; ID=4740}
I think Get-WinEvent cannot read from the evtx file the way you mentioned. Follow the approach in below link.
https://blogs.technet.microsoft.com/heyscriptingguy/2011/01/25/use-powershell-to-parse-saved-event-logs-for-errors/
Just wanted to drop a note to say thanks. I was able to modify your script here to solve a particular problem I was facing due to changed requirements. Thank you!
Hi,
and thanks for the script, which makes sense.
One further question: How can I filter the content based upon filename?
Thanks a lot in advance!
assuming you saved the script to z:\Get-zipfilecontent.ps1, and are using the Powershell shell:
PS c:\> z:\Get-zipfilecontent.ps1 .\myarchive.zip | where-object {$_.fullpath -like “*bin*”} | select-object FullPath
How can I change the script to only include the files and not the directories in the result csv file? Please guide.. Thanks in advance
Do you have an example output you are looking for?
Hello,
I need to read a password protected ziped file’s hash value without extracting it or passing the password value in the script. Will the above mentioned script work? If not, is there any alternate solution?
Thank you in advance.
The above script will not help you to generate Hash of a file. Try using Get-FileHash cmdlet. Details at https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-filehash?view=powershell-7.2