Powershell'de bir dosya nasıl açılır?


224

Bir .zipdosyam var ve Powershell kullanarak tüm içeriğini açmam gerekiyor. Bunu yapıyorum ama işe yaramıyor gibi görünüyor:

$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)
}

Sorun nedir? Dizin C:\ahala boş.


6
Powershell 2.0 veya .NET 4.5 yüklü değilse, söz konusu yöntem (3. taraf exe (yani 7zip) ile gitmeden) tek yoldur. birisi neden bu yöntemin işe yaramadığını söylüyor.Benim için zaman zaman yapıyor, ama diğerleri çalışmıyor.
kenny

Yanıtlar:


248

İşte kullanarak basit bir yoludur ExtractToDirectory dan 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"

Hedef klasör yoksa, ExtractToDirectory klasör oluşturacağını unutmayın. Diğer uyarılar:

Ayrıca bakınız:


10
Neden tek bir işlev çağrısının yerini alacak bir işlev oluşturuyorsunuz?

17
Teorik olarak yapmazsınız. İşlevlerde karmaşık / geleneksel olmayan çağrıları gizlemeye çalışıyorum, böylece daha sonra yöntemi nerede kullanıldığından endişelenmeden değiştirebilirim. Keith'in belirttiği gibi, V5'te bunu yapmanın yeni bir yolu olacak.
Micky Balladelli

1
Bunun için en az .NET Framework 4.5'e ihtiyacınız var.
Msdn.microsoft.com/en-us/library/…

10
Bunu denedim ama hata almanın altında, 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 23:16

4
Bu bana aşağıdaki hatayı veriyor: Add-Type : Cannot add type. The assembly 'System.IO.Compression.FileSystem' could not be found.. .NET 4.6.2 yükledim ve derlemenin GAC'de olduğunu doğruladım, ancak bu hatayı neden aldığımı anlayamadım.
Sam

500

PowerShell v5 + 'da yerleşik bir Genişlet-Arşiv komutu (ve ayrıca Sıkıştır-Arşivle) vardır:

Expand-Archive c:\a.zip -DestinationPath c:\a

26
$PSVersionTable.PSVersionHangi PowerShell sürümünü çalıştırdığınızı belirlemek için kullanın .
Brad C

1
@LoneCoder Ballmer'ı suçlayabileceğini sanmıyorum. 1992'de gzip çıktı ve katran daha eski olsa da, Windows daha önce sıkıştırılmış dosyaları işlemek için yerleşik bir komut satırı aracına sahip değildi .
jpmc26

2
@Ghashange PowerShell 5, bu yanıt gönderildiğinde Windows 10 ve Server 2012'nin altındaki hiçbir şey için, hatta ön sürüm olarak bile mevcut değildi.
jpmc26

11
Parametrenin OutputPathdeğiştirildiği anlaşılıyorDestinationPath (referans msdn.microsoft.com/powershell/reference/5.1/… )
Elijah W.Gagne

1
Ayrıca göreli yolları da kullanabilirsinizExpand-Archive -Path .\a.zip -DestinationPath .
Culip

24

PowerShell v5.1'de bu, v5'e kıyasla biraz farklıdır. MS belgelerine göre -Path, arşiv dosyası yolunu belirtmek için bir parametreye sahip olması gerekir .

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

Aksi takdirde, bu gerçek bir yol olabilir:

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

Belgeyi Genişlet-Arşivle


3
Bu Cmdlet'te v5 ve v5.1 arasında bir fark yoktur. İlk parametreyi adlandırmanıza gerek yoktur; otomatik olarak yol haline gelecektir. Örneğin, Expand-Archive Draft.Zip -DestinationPath C:\Referencesorunsuz çalışıyor. Ayrıca, gerçek yol değil , mutlak yol.
Franklin Yu

13

Expand-ArchiveParametre kümelerinden biriyle cmdlet kullanın :

Expand-Archive -LiteralPath C:\source\file.Zip -DestinationPath C:\destination
Expand-Archive -Path file.Zip -DestinationPath C:\destination

12

Hey benim için çalışıyor ..

$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)
}

2
Dosya veya dizinlerden biri hedef konumda zaten varsa, amacı neyin bozacağını (yoksay, üzerine yaz) soran bir iletişim kutusu açılır. Herkes sessizce üzerine yazmaya zorlamak biliyor mu?
Oleg Kazakov

@OlegKazakov tarafından yorumu cevaplamak için: CopyHereyöntemi kontrol eden bir dizi seçenek vardır . Sanırım @OlegKazakov sorununu zaten çözdü. Yine de bu konuyu bu konuyu bulabilen diğer sörfçüler için buraya koydum: docs.microsoft.com/en-us/previous-versions/windows/desktop/…
jsxt

4

Shell.Application.Namespace.Folder.CopyHere () kullanmak ve kopyalama sırasında ilerleme çubuklarını gizlemek veya daha fazla seçenek kullanmak isteyenler için, dokümantasyon burada:
https://docs.microsoft.com/en-us / windows / masa / kabuk / klasör-copyhere

Powershell kullanmak ve ilerleme çubuklarını gizlemek ve onayları devre dışı bırakmak için aşağıdaki gibi bir kod kullanabilirsiniz:

# 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)

Windows çekirdek sürümlerinde Shell.Application kullanımının kısıtlamaları:
https://docs.microsoft.com/en-us/windows-server/administration/server-core/what-is-server-core

Windows çekirdek sürümlerinde, varsayılan olarak Microsoft-Windows-Server-Shell-Package yüklü değildir, bu nedenle shell.applicaton çalışmaz.

not : arşivleri bu şekilde ayıklamak uzun zaman alacak ve windows gui yavaşlatabilir


3

expand-archiveArşivden sonra adlandırılan ancak otomatik olarak oluşturulan dizinleri kullanma :

function unzip ($file) {
    $dirname = (Get-Item $file).Basename
    New-Item -Force -ItemType directory -Path $dirname
    expand-archive $file -OutputPath $dirname -ShowProgress
}

Bu mutlaka geçerli dizinde genişler, değil mi?
jpmc26

Otomatik oluşturmanın katma değerini gerçekten görmüyorum. outputPathKabul edilen cevaptaki gibi ikinci bir parametre eklemek daha esnektir . Bu çözümde (jpmc26'nın dediği gibi), her zaman geçerli dizinde yeni bir dizin oluşturacaksınız, böylece aramadan önce geçerli dizini ayarlamanız gerekirunzip
Rubanov

Çoğu arşivleyici, arşivle aynı yerde, arşivden sonra adlandırılan bir dizine çıkar. Farklı bir şey istiyorsanız parametre eklemenizi engelleyecek bir şey yok, ancak bu mantıklı bir varsayılan.
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)
    }
}

Kullanımı:

unzip 'Applications\Site.zip' 'C:\inetpub\wwwroot\Site'

Elden unutmayın $archiveve $archiveFilesonunda
tom.maruska

0

ForEachDöngü, $filepathdeğişken içinde bulunan her ZIP dosyasını işler

    foreach($file in $filepath)
    {
        $zip = $shell.NameSpace($file.FullName)
        foreach($item in $zip.items())
        {
            $shell.Namespace($file.DirectoryName).copyhere($item)
        }
        Remove-Item $file.FullName
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.