PowerShell의 기능을 활용하면 ZIP 아카이브를 손쉽게 만들고 압축을 해제할 수 있습니다. PowerShell 5.0(Windows 10에 기본 설치된 버전)에는 전용 모듈인 Microsoft.PowerShell.Archive가 포함되어 있습니다. 그보다 오래된 Windows 버전에서는 .NET Framework의 ZipFile 클래스를 사용해 압축 작업을 처리할 수 있습니다.
Microsoft.PowerShell.Archive 모듈(C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive)에는 두 개의 cmdlet만 포함되어 있습니다.
- 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
이제 PowerShell 스크립트에서 이 cmdlet들을 활용해 ZIP 아카이브를 만들고 압축을 해제하는 다양한 예제를 살펴보겠습니다.
Compress-Archive로 ZIP 아카이브 만들기
Compress-Archive 명령의 기본 구문은 다음과 같습니다.
Compress-Archive [-Path] String[] [-DestinationPath] String [-CompressionLevel String] [-Update]
- Path – 압축할 파일 또는 폴더의 경로를 지정합니다.
- DestinationPath – 생성될 ZIP 파일의 경로를 지정합니다.
- CompressionLevel – 압축 수준을 설정합니다(
NoCompression,Optimal,Fastest). - Update – 기존 ZIP 아카이브에 파일을 추가(업데이트)할 수 있습니다.
- Force – 같은 이름의 아카이브가 이미 존재하면 덮어씁니다.
팁: 압축 수준 옵션은 다음과 같습니다.
- Optimal — 압축률을 우선적으로 최적화합니다.
- Fastest — 압축 속도를 우선적으로 최적화합니다.
- NoCompression — 압축 없이 파일만 묶습니다.
이미 압축된 형식의 파일(jpg, msi, mp3 등)을 하나의 ZIP 파일로 묶을 때는 NoCompression 옵션을 사용하는 것이 좋습니다. 이 경우 Windows가 불필요한 CPU 자원을 낭비하지 않습니다.
단일 파일을 압축하려면 다음 명령을 실행합니다.
Compress-Archive -Path "C:\Logs\WindowsUpdate.log" -DestinationPath C:\Archive\updatelog.zip -CompressionLevel Optimal
여러 폴더의 전체 내용(하위 폴더와 모든 파일 포함)도 한 번에 압축할 수 있습니다.
Compress-Archive -Path C:\Logs\,C:\Logs2\ -DestinationPath C:\Archive\logs-all.zip -CompressionLevel Optimal
여러 파일이나 폴더를 아카이브에 추가하려면 이름을 쉼표로 구분하면 됩니다.
특정 패턴과 일치하는 파일만 골라서 압축하는 것도 가능합니다. 예를 들어 다음 명령은 *.txt 파일만 압축합니다.
Compress-Archive -Path C:\Logs\*.txt -DestinationPath C:\Archive\logs-txt.zip –CompressionLevel Fastest
더 복잡한 필터링이 필요하다면 Get-ChildItem cmdlet을 활용할 수 있습니다. 예를 들어 다음 스크립트는 디스크에서 *.docx 또는 *.xlsx 확장자를 가진 파일 중 가장 큰 10개 파일을 찾아 아카이브에 추가합니다.
Get-ChildItem c:\share\ITdept -Include *.xlsx –Recurse | sort -descending -property length | select -first 10 | Compress-Archive -DestinationPath C:\backup\itdeptdocs.zip
기존 ZIP 아카이브에 새 파일을 추가하려면 Update 옵션을 사용합니다.
Compress-Archive -Path C:\Logs\,C:\logs2\ –Update -DestinationPath C:\Archive\logs-txt.zip
주의: Microsoft.PowerShell.Archive 모듈은 System.IO.Compression.ZipArchive 클래스를 기반으로 동작하기 때문에 2GB를 초과하는 파일은 압축할 수 없습니다(기본 API의 제한 때문입니다). 더 큰 파일을 압축하려고 하면 다음과 같은 오류가 발생합니다.
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
Expand-Archive로 ZIP 파일 압축 해제하기
ZIP 파일의 압축을 해제하려면 Expand-Archive cmdlet을 사용합니다. 구문은 Compress-Archive와 유사합니다.
Expand-Archive [-Path] String [-DestinationPath] String [-Force] [-Confirm]
예를 들어 앞서 만든 ZIP 아카이브를 지정한 폴더에 압축 해제하고 기존 파일을 덮어쓰려면 다음과 같이 실행합니다.
Expand-Archive -Path C:\archive\logs-all.zip -DestinationPath c:\logs -Force
Microsoft.PowerShell.Archive 모듈의 단점은 다음과 같습니다.
- 압축을 해제하지 않고는 아카이브 내용을 확인할 수 없습니다.
- 아카이브에서 일부 파일만 선택적으로 추출할 수 없습니다(전체 아카이브를 풀어야 합니다).
- zip 외의 다른 압축 형식은 지원하지 않습니다.
- ZIP 아카이브에 암호를 설정할 수 없습니다.
더 복잡한 작업이 필요하다면 PowerShell 스크립트에서 서드파티 도구를 사용해야 합니다. 대표적으로 7zip이나 7Zip4Powershell 모듈이 있습니다.
7Zip4Powershell 모듈을 설치하고 암호로 보호된 ZIP 파일을 압축 해제하는 방법은 다음과 같습니다.
Install-Module -Name 7Zip4Powershell
Expand-7Zip -ArchiveFileName C:\Archive\Logs.zip -Password "p@ssd0rw" -TargetPath C:\Share\Logs
PowerShell ZipFile 클래스로 압축 파일 다루기
Windows 10 또는 Windows Server 2016 이전 버전(PowerShell 5.0 미만이며 버전 업그레이드가 불가능한 환경)에서는 .NET Framework 4.5의 ZipFile 클래스를 사용해 ZIP 아카이브를 만들 수 있습니다.
먼저 PowerShell 세션에 해당 클래스를 로드합니다.
Add-Type -AssemblyName "System.IO.Compression.FileSystem"
폴더 전체를 압축하려면 다음과 같은 PS 스크립트를 사용합니다.
$SourceFolder = 'C:\Logs'
$ZipFileName = 'C:\PS\logs.zip'
[IO.Compression.ZipFile]::CreateFromDirectory($SourceFolder, $ZipFileName)
ZIP 아카이브를 업데이트하고 압축률을 지정하려면 다음 PowerShell 코드를 사용합니다.
$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()
$zip.Dispose() 명령은 ZIP 파일을 닫는 데 사용됩니다.
ZIP 아카이브의 내용 목록도 확인할 수 있습니다.
[System.IO.Compression.ZipFile]::OpenRead($zipFileName).Entries.Name
또는 Out-GridView 테이블을 활용하면 압축/비압축 파일 크기, 마지막 수정 시간 등 추가 정보와 함께 ZIP 아카이브 내용을 한눈에 확인할 수 있습니다.
$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()
ZIP 파일을 C:\Logs 폴더에 압축 해제하려면 다음 명령을 사용합니다.
$SourceZipFile = 'C:\PS\logs.zip'
$TargetFolder = 'C:\Logs'
[IO.Compression.ZipFile]::ExtractToDirectory($SourceZipFile, $TargetFolder)