Bagaimana cara unzip file di Powershell?

224

Saya punya .zipfile dan perlu membongkar seluruh kontennya menggunakan Powershell. Saya melakukan ini tetapi sepertinya tidak berhasil:

$shell = New-Object -ComObject shell.application
$zip = $shell.NameSpace("C:\a.zip")
MkDir("C:\a")
foreach ($item in $zip.items()) {
  $shell.Namespace("C:\a").CopyHere($item)
}

Apa yang salah? Direktori C:\amasih kosong.

Uli Kunkel
sumber
6
Jika Anda berada di Powershell 2.0, atau tanpa .NET 4.5 diinstal, maka metode yang Anda sebutkan adalah satu-satunya jalan (tanpa menggunakan exe pihak ke-3 (yaitu 7zip). Saya akan mengatakan bahwa pertanyaannya tidak sepenuhnya dijawab hingga seseorang memberi alasan mengapa metode ini tidak berhasil untuk saya beberapa waktu, tetapi yang lain tidak berhasil
kenny

Jawaban:

248

Berikut adalah cara sederhana menggunakan ExtractToDirectory dari System.IO.Compression.ZipFile :

Add-Type -AssemblyName System.IO.Compression.FileSystem
function Unzip
{
    param([string]$zipfile, [string]$outpath)

    [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
}

Unzip "C:\a.zip" "C:\a"

Perhatikan bahwa jika folder target tidak ada, ExtractToDirectory akan membuatnya. Peringatan lainnya:

Lihat juga:

Micky Balladelli
sumber
10
Mengapa Anda membuat fungsi untuk mengganti panggilan fungsi tunggal?
17
Secara teori Anda tidak. Saya mencoba untuk menyembunyikan panggilan kompleks / tidak konvensional dalam fungsi sehingga nantinya saya dapat mengganti metode tanpa khawatir di mana itu digunakan. Seperti yang disebutkan Keith, di V5 akan ada cara baru untuk melakukannya.
Micky Balladelli
1
Anda memerlukan setidaknya .NET Framework 4.5 untuk ini. Lihat bagian bawah msdn.microsoft.com/en-us/library/…
ferventcoder
10
Saya mencoba ini tetapi mendapatkan kesalahan di bawah ini, Exception calling "ExtractToDirectory" with "2" argument(s): "End of Central Directory record could not be found." At line:5 char:5 + [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $ou ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : InvalidDataException
Karthi1234
4
Ini memberi saya error berikut: Add-Type : Cannot add type. The assembly 'System.IO.Compression.FileSystem' could not be found.. Saya telah menginstal .NET 4.6.2, dan saya telah memverifikasi bahwa perakitan di GAC, tapi saya tidak tahu mengapa saya mendapatkan kesalahan ini.
Sam
500

Di PowerShell v5 +, ada perintah Expand-Archive (dan juga Compress-Archive) bawaan:

Expand-Archive c:\a.zip -DestinationPath c:\a
Keith Hill
sumber
26
Gunakan $PSVersionTable.PSVersionuntuk menentukan versi PowerShell apa yang Anda jalankan.
Brad C
1
@LoneCoder Saya tidak berpikir Anda bisa menyalahkan Ballmer. Windows tidak pernah memiliki alat baris perintah bawaan untuk menangani file terkompresi sebelumnya, meskipun gzip keluar pada tahun 1992 dan tar bahkan lebih tua.
jpmc26
2
@ Ghashange PowerShell 5 bahkan tidak tersedia untuk apa pun di bawah Windows 10 dan Server 2012 ketika jawaban ini diposting, bahkan sebagai pra-rilis.
jpmc26
11
Sepertinya parameter OutputPathtelah diubah menjadi DestinationPath(referensi msdn.microsoft.com/powershell/reference/5.1/… )
Elijah W. Gagne
1
Anda juga dapat menggunakan jalur relatif sepertiExpand-Archive -Path .\a.zip -DestinationPath .
Culip
24

Di PowerShell v5.1 ini sedikit berbeda dibandingkan dengan v5. Menurut dokumentasi MS, itu harus memiliki -Pathparameter untuk menentukan path file arsip.

Expand-Archive -Path Draft.Zip -DestinationPath C:\Reference

Atau yang lain, ini bisa menjadi jalan yang sebenarnya:

Expand-Archive -Path c:\Download\Draft.Zip -DestinationPath C:\Reference

Expand-Archive Doc

NIK
sumber
3
Tidak ada perbedaan antara v5 dan v5.1 di Cmdlet ini. Anda tidak perlu memberi nama parameter pertama; itu akan secara otomatis menjadi jalan. Misalnya, Expand-Archive Draft.Zip -DestinationPath C:\Referencebekerja tanpa masalah. Selain itu, ini bukan jalur yang sebenarnya , tetapi jalur absolut .
Franklin Yu
13

Gunakan Expand-Archivecmdlet dengan salah satu dari set parameter:

Expand-Archive -LiteralPath C:\source\file.Zip -DestinationPath C:\destination
Expand-Archive -Path file.Zip -DestinationPath C:\destination
Saleh Rahimzadeh
sumber
12

Hai ini bekerja untuk saya ..

$shell = New-Object -ComObject shell.application
$zip = $shell.NameSpace("put ur zip file path here")
foreach ($item in $zip.items()) {
  $shell.Namespace("destination where files need to unzip").CopyHere($item)
}
Abhijit
sumber
2
Jika salah satu file atau direktori sudah ada di lokasi tujuan, muncul dialog yang menanyakan apa yang harus dilakukan (abaikan, timpa) yang mengalahkan tujuannya. Adakah yang tahu bagaimana memaksanya untuk menimpa secara diam-diam?
Oleg Kazakov
Menjawab komentar oleh @OlegKazakov: ada beberapa opsi untuk mengendalikan CopyHeremetode ini. Saya kira @OlegKazakov sudah menyelesaikan masalahnya. Namun demikian saya meletakkan tautan ini di sini untuk peselancar lain yang dapat menemukan topik ini: docs.microsoft.com/en-us/previous-versions/windows/desktop/…
jsxt
4

Bagi mereka yang ingin menggunakan Shell.Application.Namespace.Folder.CopyHere () dan ingin menyembunyikan progress bar saat menyalin, atau menggunakan lebih banyak opsi, dokumentasi ada di sini:
https://docs.microsoft.com/en-us / windows / desktop / shell / folder-copyhere

Untuk menggunakan PowerShell dan menyembunyikan progress bar dan menonaktifkan konfirmasi, Anda dapat menggunakan kode seperti ini:

# We should create folder before using it for shell operations as it is required
New-Item -ItemType directory -Path "C:\destinationDir" -Force

$shell = New-Object -ComObject Shell.Application
$zip = $shell.Namespace("C:\archive.zip")
$items = $zip.items()
$shell.Namespace("C:\destinationDir").CopyHere($items, 1556)

Keterbatasan penggunaan Shell.Application pada versi inti windows:
https://docs.microsoft.com/en-us/windows-server/administration/server-core/what-is-server-core

Pada versi windows core , secara default Microsoft-Windows-Server-Shell-Package tidak diinstal, jadi shell.applicaton tidak akan berfungsi.

Catatan : Mengekstrak arsip dengan cara ini akan memakan waktu lama dan dapat memperlambat windows gui

Matej Ridzon
sumber
3

Menggunakan expand-archivetetapi menciptakan direktori secara otomatis dinamai arsip:

function unzip ($file) {
    $dirname = (Get-Item $file).Basename
    New-Item -Force -ItemType directory -Path $dirname
    expand-archive $file -OutputPath $dirname -ShowProgress
}
mikemaccana
sumber
Ini perlu diperluas di direktori saat ini, bukan?
jpmc26
Tidak benar-benar melihat nilai tambah dari penciptaan otomatis. Lebih fleksibel untuk menambahkan parameter kedua outputPathseperti pada jawaban yang diterima. Dalam solusi ini (seperti yang dikatakan jpmc26), Anda akan selalu membuat direktori baru di direktori saat ini sehingga mungkin Anda perlu mengatur direktori saat ini sebelum meneleponunzip
Rubanov
Sebagian besar pengarsipan mengekstrak ke dir yang dinamai arsip, di tempat yang sama dengan arsip. Tidak ada yang menghentikan Anda menambahkan parameter jika Anda menginginkan sesuatu yang berbeda, tetapi ini adalah default yang masuk akal.
mikemaccana
1
function unzip {
    param (
        [string]$archiveFilePath,
        [string]$destinationPath
    )

    if ($archiveFilePath -notlike '?:\*') {
        $archiveFilePath = [System.IO.Path]::Combine($PWD, $archiveFilePath)
    }

    if ($destinationPath -notlike '?:\*') {
        $destinationPath = [System.IO.Path]::Combine($PWD, $destinationPath)
    }

    Add-Type -AssemblyName System.IO.Compression
    Add-Type -AssemblyName System.IO.Compression.FileSystem

    $archiveFile = [System.IO.File]::Open($archiveFilePath, [System.IO.FileMode]::Open)
    $archive = [System.IO.Compression.ZipArchive]::new($archiveFile)

    if (Test-Path $destinationPath) {
        foreach ($item in $archive.Entries) {
            $destinationItemPath = [System.IO.Path]::Combine($destinationPath, $item.FullName)

            if ($destinationItemPath -like '*/') {
                New-Item $destinationItemPath -Force -ItemType Directory > $null
            } else {
                New-Item $destinationItemPath -Force -ItemType File > $null

                [System.IO.Compression.ZipFileExtensions]::ExtractToFile($item, $destinationItemPath, $true)
            }
        }
    } else {
        [System.IO.Compression.ZipFileExtensions]::ExtractToDirectory($archive, $destinationPath)
    }
}

Menggunakan:

unzip 'Applications\Site.zip' 'C:\inetpub\wwwroot\Site'
pengguna1624251
sumber
Jangan lupa untuk membuang $archivedan $archiveFilepada akhirnya
tom.maruska
0

ForEachLoop memproses setiap file ZIP yang terletak di dalam $filepathvariabel

    foreach($file in $filepath)
    {
        $zip = $shell.NameSpace($file.FullName)
        foreach($item in $zip.items())
        {
            $shell.Namespace($file.DirectoryName).copyhere($item)
        }
        Remove-Item $file.FullName
    }
Pradyumna
sumber