Làm cách nào để giải nén một tập tin trong Powershell?


224

Tôi có một .ziptệp và cần giải nén toàn bộ nội dung của nó bằng Powershell. Tôi đang làm điều này nhưng nó dường như không hoạt động:

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

Chuyện gì vậy? Thư mục C:\avẫn trống.


6
Nếu bạn đang cài đặt Powershell 2.0 hoặc chưa cài đặt .NET 4.5, thì phương thức bạn đã đề cập là đường dẫn duy nhất (không đi với exe của bên thứ 3 (tức là 7zip). Tôi sẽ nói rằng câu hỏi chưa được trả lời đầy đủ cho đến khi ai đó cung cấp lý do tại sao phương pháp này không hiệu quả. Nó đôi khi đối với tôi, nhưng những người khác thì không.
kenny

Câu trả lời:


248

Đây là một cách đơn giản bằng cách sử dụng ExtractToDirectory từ 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"

Lưu ý rằng nếu thư mục đích không tồn tại, ExtractToDirectory sẽ tạo nó. Hãy cẩn thận khác:

Xem thêm:


10
Tại sao bạn tạo một chức năng để thay thế một cuộc gọi chức năng duy nhất?

17
Về lý thuyết bạn không. Tôi cố gắng ẩn các cuộc gọi phức tạp / độc đáo trong các chức năng để sau này tôi có thể thay thế phương thức mà không phải lo lắng về việc nó được sử dụng ở đâu. Như Keith đã đề cập, trong V5 sẽ có một cách mới để làm điều đó.
Micky Balladelli

1
Bạn cần ít nhất .NET Framework 4.5 cho việc này. Xem phần dưới cùng của msdn.microsoft.com/en-us/l
Library / từ

10
Tôi đã thử cách này nhưng gặp lỗi dưới đây, 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
Điều này cho tôi các lỗi sau : Add-Type : Cannot add type. The assembly 'System.IO.Compression.FileSystem' could not be found.. Tôi đã cài đặt .NET 4.6.2 và tôi đã xác minh rằng hội đồng này nằm trong GAC, nhưng tôi không hiểu tại sao tôi lại gặp lỗi này.
Sam

500

Trong PowerShell v5 +, có lệnh Mở rộng-Lưu trữ (cũng như Nén-Lưu trữ) được tích hợp:

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

26
Sử dụng $PSVersionTable.PSVersionđể xác định phiên bản PowerShell bạn đang chạy.
Brad C

1
@LoneCoder Tôi không nghĩ bạn có thể đổ lỗi cho Ballmer. Windows chưa bao giờ có một công cụ dòng lệnh tích hợp để xử lý các tệp nén trước đó, mặc dù gzip ra đời vào năm 1992 và tar thậm chí còn cũ hơn.
jpmc26

2
@Ghashange PowerShell 5 thậm chí không có sẵn cho bất cứ điều gì bên dưới Windows 10 và Server 2012 khi câu trả lời này được đăng, ngay cả khi là bản phát hành trước.
jpmc26

11
Có vẻ như tham số OutputPathđã được thay đổi thành DestinationPath(tham khảo msdn.microsoft.com/powershell/reference/5.1/ Lời )
Elijah W. Gagne

1
Bạn cũng có thể sử dụng các đường dẫn tương đối nhưExpand-Archive -Path .\a.zip -DestinationPath .
Culip

24

Trong PowerShell v5.1, điều này hơi khác so với v5. Theo tài liệu MS, nó phải có một -Paththam số để chỉ định đường dẫn tệp lưu trữ.

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

Hoặc nếu không, đây có thể là một đường dẫn thực tế:

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

Mở rộng-Lưu trữ tài liệu


3
Không có sự khác biệt giữa v5 và v5.1 trong Cmdlet này. Bạn không cần đặt tên cho tham số đầu tiên; nó sẽ tự động trở thành đường dẫn Ví dụ, Expand-Archive Draft.Zip -DestinationPath C:\Referencehoạt động mà không có vấn đề. Ngoài ra, đó không phải là con đường thực tế , mà là con đường tuyệt đối .
Franklin Yu

13

Sử dụng Expand-Archivelệnh ghép ngắn với một trong các tham số được đặt:

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

12

Này nó làm việc cho tôi ..

$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
Nếu một trong các tệp hoặc thư mục đã tồn tại ở vị trí đích, nó sẽ bật lên một cuộc đối thoại hỏi phải làm gì (bỏ qua, ghi đè) mà đánh bại mục đích. Có ai biết làm thế nào để buộc nó âm thầm ghi đè?
Oleg Kazakov

Trả lời nhận xét của @OlegKazakov: có bộ tùy chọn kiểm soát CopyHerephương thức. Tôi đoán @OlegKazakov đã giải quyết vấn đề của mình. Tuy nhiên, tôi đặt liên kết này ở đây cho những người lướt web khác có thể tìm thấy chủ đề này: docs.microsoft.com/en-us/preingly-versions/windows/desktop/ phỏng
jsxt

4

Đối với những người muốn sử dụng Shell.Application.Namespace.Folder.CopyHere () và muốn ẩn các thanh tiến trình trong khi sao chép hoặc sử dụng nhiều tùy chọn hơn, tài liệu có tại đây:
https://docs.microsoft.com/en-us / windows / desktop / shell / thư mục-copyhere

Để sử dụng powershell và ẩn các thanh tiến trình và vô hiệu hóa xác nhận, bạn có thể sử dụng mã như thế này:

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

Hạn chế của việc sử dụng Shell.Ứng dụng trên các phiên bản lõi của windows:
https://docs.microsoft.com/en-us/windows-server/ad

Trên các phiên bản lõi của windows , theo mặc định, Microsoft-Windows-Server-Shell-Gói không được cài đặt, vì vậy shell.applicaton sẽ không hoạt động.

lưu ý : Trích xuất tài liệu lưu trữ theo cách này sẽ mất nhiều thời gian và có thể làm chậm cửa sổ gui


3

Sử dụng expand-archivenhưng tự động tạo thư mục được đặt tên theo kho lưu trữ:

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

Điều này nhất thiết phải mở rộng trong thư mục hiện tại, phải không?
jpmc26

Không thực sự thấy giá trị gia tăng của việc tạo tự động. Sẽ linh hoạt hơn khi thêm một tham số thứ hai outputPathnhư trong câu trả lời được chấp nhận. Trong giải pháp này (như jpmc26 đã nói), bạn sẽ luôn tạo một thư mục mới trong thư mục hiện tại để có thể bạn cần đặt thư mục hiện tại trước khi bạn gọiunzip
Rubanov

Hầu hết các lưu trữ trích xuất vào một thư mục được đặt tên theo kho lưu trữ, ở cùng một nơi với kho lưu trữ. Không có gì ngăn bạn thêm các tham số nếu bạn muốn một cái gì đó khác biệt, nhưng đó là một mặc định hợp lý.
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)
    }
}

Sử dụng:

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

Đừng quên vứt bỏ $archive$archiveFilecuối cùng
tom.maruska

0

ForEachVòng lặp xử lý mỗi tệp ZIP nằm trong $filepathbiến

    foreach($file in $filepath)
    {
        $zip = $shell.NameSpace($file.FullName)
        foreach($item in $zip.items())
        {
            $shell.Namespace($file.DirectoryName).copyhere($item)
        }
        Remove-Item $file.FullName
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.