Extract Specific Filetypes From Multiple Zips to one Folder in Powershell

夙愿已清 提交于 2021-01-29 15:47:36

问题


I have Several zip files that Contain multiple filetypes. The ONLY ones I am interested in are the .txt files. I need to extract the .txt files only and place them in a folder of their own, ignoring all other file types in the zips files.

All the zip files are in the same folder.

Example

-foo.zip

--1.aaa
--2.bbb
--3.ccc
--4.txt

-foo2.zip

--5.aaa
--6.bbb
--7.ccc
--8.txt

I want to have 4.txt and 8.txt extracted to another folder. I can't for the life of my figure it out and spent ages looking, googling and trying. Even managing to delete to zips once in a while :-)

Thanks in advance


回答1:


Use the ZipArchive type to programmatically inspect the archive before extracting:

Add-Type -AssemblyName System.IO.Compression

$destination = "C:\destination\folder"

# Locate zip file
$zipFile = Get-Item C:\path\to\file.zip

# Open a read-only file stream
$zipFileStream = $zipFile.OpenRead()

# Instantiate ZipArchive
$zipArchive = [System.IO.Compression.ZipArchive]::new($zipFileStream)

# Iterate over all entries and pick the ones you like
foreach($entry in $zipArchive.Entries){
    if($entry.Name -like '*.txt'){
        # Create new file on disk, open writable stream
        $targetFileStream = $(
            New-Item -Path $destination -Name $entry.Name -ItemType File
        ).OpenWrite()

        # Open stream to compressed file, copy to new file stream
        $entryStream = $entry.Open()
        $entryStream.BaseStream.CopyTo($targetFileStream)

        # Clean up
        $targetFileStream,$entryStream |ForEach-Object Dispose
    }
}

# Clean up
$zipArchive,$zipFileStream |ForEach-Object Dispose

Repeat for each zip file.

Note that the code above has very minimal error-handling, and is to be read as an example




回答2:


Try this:

Set-Location "Extraction path"
@("full path of foo.zip","full path of foo2.zip") | ForEach {
  & "Full path of 7z.exe" x '-i!*.txt' $_.FullName
}
  • Sets location to the path where files will be extracted.

  • Passes a array of zip files to for loop.

  • Exexute 7z command to extract only zip files.




回答3:


Here is one approach:

  1. Go through each .zip file in a folder.
  2. Extract archive into separate folder.
  3. Extract .txt file from folder.
  4. Copy files into destination folder containing all .txt files. This will overwrite files if they already exist in the destination folder.
  5. Cleanup extracted folders once finished.

Demo:

function Copy-ZipArchiveFiles {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if (-not(Test-Path $_ -PathType Container))
            {
                throw "The source path $_ does not exist. Please enter a valid source path."
            }
            else
            {
                $true
            }
        })]
        [string]$Path,
        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if ([string]::IsNullOrEmpty($_.Trim()))
            {
                throw "The Destination path is null or empty. Please enter a valid destination path."
            } 
            else 
            {
                $true
            }
        })]
        [string]$Destination,
        [Parameter(Mandatory=$false)]
        [AllowNull()]
        [AllowEmptyString()]
        [AllowEmptyCollection()]
        [string[]]$Include
    )

    # Create destination folder if it doesn't already exist
    if (-not(Test-Path -Path $Destination -PathType Container))
    {
        try 
        {
            New-Item -Path $Destination -ItemType Directory -ErrorAction Stop
        }
        catch
        {
            throw "The destination path $Destination is invalid. Please enter a valid destination path."
        }
    }

    # Go through each .zip file
    foreach ($zipFile in Get-ChildItem -Path $Path -Filter *.zip)
    {

        # Get folder name from zip file w/o .zip at the end
        $zipFolder = Split-Path $zipFile -LeafBase

        # Get full folder path
        $folderPath = Join-Path -Path $Path -ChildPath $zipFolder

        # Expand .zip file into folder if it doesn't exist
        if (-not(Test-Path -Path $folderPath -PathType Container)) 
        {
            Expand-Archive -Path $zipFile.FullName -DestinationPath $folderPath
        }

        # Copy files into destination folder
        foreach ($file in Get-ChildItem $folderPath -Include $Include -Recurse)
        {
            Copy-Item -Path $file.FullName -Destination $Destination
        }

        # Delete extracted folders
        Remove-Item -Path $folderPath -Recurse -Force
    }
}

Usage:

Copy-ZipArchiveFiles `
    -Path "C:\path\to\zip\files" `
    -Destination "C:\path\to\text\files" `
    -Include "*.txt"

Note: Could also use this for multiple extension types as well by passing -Include *.txt, *.pdf. I also went a bit overboard in the parameter error checking, but I believe in writing robust code. Good habit to get into when writing your own cmdlets anyways :)



来源:https://stackoverflow.com/questions/61365057/powershell-extract-the-content-of-subfolder-of-zip-archive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!