≡ Menu

Reading ZIP file contents without extraction using PowerShell

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.

  • HDang August 3, 2015, 3:15 pm

    Thanks! This worked for me perfectly! am using it to actually search for a files within thousands of zip files…

    • TechiBee August 23, 2015, 8:59 pm

      Glad to know that it helped

  • Timothy Wright November 10, 2015, 3:25 am

    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.

    • TechiBee January 4, 2016, 4:56 pm

      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.

  • Robert Ferguson December 23, 2015, 4:22 am

    This looks great however I need to search a director file with zip files for a string. Thoughts?

    • TechiBee January 4, 2016, 5:04 pm

      Can you give an example?

      • Underdog October 7, 2016, 10:42 pm

        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.

  • tif January 29, 2016, 4:02 am

    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.

  • Johnny C February 12, 2016, 6:42 pm

    nice one! how can I use this to read an XML file inside a zip?

  • kaushik May 9, 2016, 4:27 pm

    “PowerShell 3” required for successful execution of this program.

    • corey May 25, 2018, 9:35 pm

      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.

  • Val July 1, 2016, 3:14 am

    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

    • Wintel Rocks July 9, 2016, 9:41 am

      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.

  • Mark August 12, 2016, 12:47 am

    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.

  • Carlos August 12, 2016, 1:20 am

    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}

  • Vitaliy April 29, 2017, 2:53 am

    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!

  • Dirk September 5, 2017, 1:55 pm

    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!

    • corey May 25, 2018, 9:40 pm

      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

  • Vishesh Amarpuri April 1, 2020, 2:10 am

    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

    • Wintel Rocks May 10, 2020, 7:46 pm

      Do you have an example output you are looking for?

  • Gargi November 8, 2021, 9:24 am

    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.