Bạn có thể dùng tính năng PowerShell để tạo file ZIP và giải nén chúng. Trong PowerShell 5.0 (phiên bản PowerShell này được cài mặc định trên Windows 10), một module riêng Microsoft.PowerShell.Archive có sẵn. Trên các phiên bản Windows cũ hơn, bạn có thể dùng lớp ZipFile từ .NET Framework để nén.
Chỉ có hai cmdlet trong module Microsoft.PowerShell.Archive (C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive):
- Compress-Archive
- Expand-Archive
Get-Command -Module Microsoft.PowerShell.Archive | Format-Table -AutoSize
CommandType Name Version Source ----------- ---- ------- ------ Function Compress-Archive 1.0.1.0 Microsoft.PowerShell.Archive Function Expand-Archive 1.0.1.0 Microsoft.PowerShell.Archive
Hãy xem ví dụ dùng các cmdlet này để tạo và giải nén file ZIP trong script PowerShell của bạn.
PowerShell: Tạo file ZIP với Compress-Archive
Lệnh Compress-Archive có cú pháp sau:
Compress-Archive [-Path] String[] [-DestinationPath] String [-CompressionLevel String ] [-Update]
- Tham số Path dùng để chỉ định đường dẫn đến file hoặc thư mục cần nén;
- DestinationPath – chỉ định đường dẫn đến file ZIP;
- CompressionLevel – đặt mức nén (
NoCompression,OptimalhoặcFastest); - Update – cho phép thêm (cập nhật) file vào file ZIP đã tồn tại;
- Force – nếu file nén với tên chỉ định đã tồn tại, nó sẽ bị ghi đè.
Mẹo. Tùy chọn mức nén:
- Optimal — tối ưu theo mức độ nén;
- Fastest — tối ưu theo thời gian thực hiện;
- NoCompression — không nén.
Tùy chọn NoCompression nên dùng khi nén file đã nén (jpg, msi, mp3, v.v.) vào một file ZIP duy nhất. Trong trường hợp này, Windows sẽ không lãng phí thời gian CPU nén chúng.
Để nén một file đơn, chạy:
Compress-Archive -Path "C:\Logs\WindowsUpdate.log" -DestinationPath C:\Archive\updatelog.zip -CompressionLevel Optimal
Bạn có thể nén toàn bộ nội dung nhiều thư mục (bao gồm tất cả file và thư mục lồng nhau):
Compress-Archive -Path C:\Logs\,C:\Logs2\ -DestinationPath C:\Archive\logs-all.zip -CompressionLevel Optimal
Để thêm nhiều file hoặc thư mục vào file nén, tách tên của chúng bằng dấu phẩy.
Bạn có thể thêm vào file ZIP chỉ file với mask cụ thể. Ví dụ, lệnh sau sẽ chỉ nén file *.txt.
Compress-Archive -Path C:\Logs\*.txt -DestinationPath C:\Archive\logs-txt.zip –CompressionLevel Fastest
Bộ lọc phức tạp hơn có thể dùng với cmdlet Get-ChildItem. Ví dụ, script sau cho phép bạn tìm 10 file lớn nhất với phần mở rộng *.docx hoặc *.xlsx trên ổ đĩa và thêm chúng vào file nén:
Get-ChildItem c:\share\ITdept -Include *.xlsx –Recurse| sort -descending -property length | select -first 10 |Compress-Archive -DestinationPath C:\backup\itdeptdocs.zip
Để thêm file mới vào file zip đã tồn tại, dùng khóa Update:
Compress-Archive -Path C:\Logs\,C:\logs2\ –Update -DestinationPath C:\Archive\logs-txt.zip
Mẹo. Vì module Microsoft.PowerShell.Archive dùng lớp System.IO.Compression.ZipArchive, bạn không thể nén file lớn hơn 2 GB (vì có giới hạn của API nền tảng). Khi cố nén file lớn hơn, lỗi sẽ xuất hiện:
Exception calling "Write" with "3" argument(s): "Stream was too long." At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive\Microsoft.PowerShell.Archive.psm1:805 char:29 + ... $destStream.Write($buffer, 0, $numberOfBytesRead) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : IOException
Cách giải nén file ZIP với Expand-Archive?
Bạn có thể dùng cmdlet Expand-Archive để giải nén file ZIP. Cú pháp cho cmdlet tương tự:
Expand-Archive [-Path] String [-DestinationPath] String [-Force] [-Confirm]
Ví dụ, để giải nén file ZIP chúng ta tạo trước đó vào thư mục chỉ định và ghi đè file:
Expand-Archive -Path C:\archive\logs-all.zip -DestinationPath c:\logs -Force
Nhược điểm của module Microsoft.PowerShell.Archive:
- Bạn không thể xem nội dung file nén mà không giải nén nó;
- Bạn không thể giải nén một phần file từ file nén (bạn phải giải nén toàn bộ file nén);
- Bạn không thể dùng định dạng file nén khác, trừ zip;
- Bạn không thể bảo vệ file ZIP bằng mật khẩu.
Trong các trường hợp phức tạp hơn, bạn cần dùng công cụ bên thứ ba để nén trong script PowerShell. Ví dụ, 7zip hoặc module 7Zip4Powershell.
Bạn có thể cài module 7Zip4Powershell và giải nén file zip có mật khẩu như sau:
Install-Module -Name 7Zip4Powershell
Expand-7Zip -ArchiveFileName C:\Archive\Logs.zip -Password "p@ssd0rw" -TargetPath C:\Share\Logs
Làm việc với file nén bằng lớp PowerShell ZipFile
Trong các phiên bản Windows trước (trước Windows 10 hoặc Windows Server 2016 với phiên bản PowerShell < 5.0 (nếu bạn không thể nâng cấp phiên bản PowerShell), bạn có thể dùng lớp ZipFile riêng (từ NET Framework 4.5) để tạo file zip.
Trước hết, nạp lớp vào phiên PowerShell của bạn:
Add-Type -AssemblyName "System.IO.Compression.FileSystem"
Để nén thư mục, dùng script PS như sau:
$SourceFolder = 'C:\Logs'
$ZipFileName = 'C:\PS\logs.zip'
[IO.Compression.ZipFile]::CreateFromDirectory($SourceFolder, $ZipFileName)
Để cập nhật file ZIP và đặt tỷ lệ nén, dùng mã PowerShell sau:
$addfile = 'C:\temp\new.log'
$compressionLevel = [System.IO.Compression.CompressionLevel]::Fastest
$zip = [System.IO.Compression.ZipFile]::Open($zipFileName, 'update')
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $addfile, (Split-Path $addfile -Leaf), $compressionLevel)
$zip.Dispose()
Lệnh $zip.Dispose() dùng để đóng file zip.
Bạn có thể liệt kê nội dung file ZIP:
[System.IO.Compression.ZipFile]::OpenRead($zipFileName).Entries.Name
Hoặc bạn có thể hiển thị nội dung file zip dưới dạng bảng Out-GridView với thông tin thêm (kích thước file nén/chưa nén, thời gian ghi cuối, v.v.):
$ZipFileName = "C:\PS\logs1.zip"
$Stream = New-Object IO.FileStream($ZipFileName , [IO.FileMode]::Open)
$ZipArchive = New-Object IO.Compression.ZipArchive($Stream)
$ZipArchive.Entries |
Select-Object Name,
@{Name="File Path";Expression={$_.FullName}},
@{Name="Compressed Size (KB)";Expression={"{0:N2}" -f($_.CompressedLength/1kb)}},
@{Name="UnCompressed Size (KB)";Expression={"{0:N2}" -f($_.Length/1kb)}},
@{Name="File Date";Expression={$_.LastWriteTime}} | Out-GridView
$ZipArchive.Dispose()
$Stream.Close()
$Stream.Dispose()
Để giải nén file ZIP vào thư mục C:\Logs, dùng các lệnh sau:
$SourceZipFile = 'C:\PS\logs.zip'
$TargetFolder = 'C:\Logs'
[IO.Compression.ZipFile]::ExtractToDirectory($SourceZipFile, $TargetFolder)