programing

압축-archive 및 상대 경로 보존

yellowcard 2023. 11. 1. 22:15
반응형

압축-archive 및 상대 경로 보존

저는 그들을 이해하는 데 힘든 시간을 보내고 있습니다.compress-archive내가 하고 싶은 일을...

루트 프로젝트 폴더가 있는데 하위 디렉토리에 있는 파일 중 일부를 압축하고 관련 경로를 보존하고 싶습니다.예를 들어, / ├── _scripts ├── ├─_module1 | | └── filex.js | └─_module2 | ├── file1.js | └── file2.txt

그래서 루트 디렉터리에서 다음을 포함하는 zip 파일을 만들고 싶습니다.module2/*, 그리고 폴더 구조를 유지하고 싶습니다.제 우편물에 다음 내용이 포함되어 있으면 좋겠습니다. scripts/module2/file1.js scripts/module2/file2.txt

그러나 루트 폴더에서 이 작업을 실행하면 다음과 같습니다.Compress-Archive -Path "scripts\module2\*" -DestinationPath tmp.zip

zip 파일의 내용은 다음 내용만 포함합니다. /file1.js /file2.txt

는 것으로 보입니다.Compress-Archive(Windows PowerShell v5.1 기준)에서는 다음을 지원하지 않습니다.

폴더를 대상으로 지정하면 해당 폴더의 하위 트리가 재귀적으로 아카이브에 추가되지만, 대상 폴더의 이름(아카이브 내의 하위 폴더가 됨)에 의해서만 해당 경로가 추가되지 않습니다.

구체적으로.

Compress-Archive -Path scripts\module2 -DestinationPath tmp.zip

의 내용을 (recurs적으로) 저장할 것.scripts\module2인에tmp.zip, archive-internal path를 사용하지 않습니다..\scripts\module2, 와 함께.\module2- 대상 폴더의 이름(마지막 입력 경로 구성 요소).

그 의미는 당신이 폴더를 넘겨야 한다는 것입니다.scripts원하는 아카이브-내부 경로를 얻는 대신, 그것은 항상 전체 하위 트리를 포함할 것입니다.scripts, 라는 점을 감안하면Compress-Archive포함/exclusion 메커니즘을 제공하지 않습니다.


한 가지 - 번거로운 - 옵션은 예를 들어, 원하는 계층 구조를 다시 만드는 것입니다.$env:TEMP폴더, 대상 폴더 복사, 실행Compress-Archive재작성된 계층의 근본에 대해 다음을 정리합니다.

New-Item -Force -ItemType Directory $env:TEMP/scripts
Copy-Item -Recurse -Force scripts/module2 $env:TEMP/scripts
Compress-Archive -LiteralPath $env:TEMP/scripts -DestinationPath tmp.zip
Remove-Item $env:TEMP/Scripts -Recurse -Whatif

그렇지 않으면 다음과 같은 해결책을 찾을 수 있습니다.

  • 을 사용하여NET v4.5+ 클래스를 직접 사용할 수 있습니다.Add-Type -Assembly System.IO.Compression.FileSystem(PowerShell Core에는 필요 없음).

  • 7-Zip과 같은 외부 프로그램을 사용함으로써,

전체 구조를 임시 디렉토리에 복사할 필요 없이 이 작업을 수행하고 싶었습니다.

#build list of files to compress
$files = @(Get-ChildItem -Path .\procedimentos -Recurse | Where-Object -Property Name -EQ procedimentos.xlsx);
$files += @(Get-ChildItem -Path .\procedimentos -Recurse | Where-Object -Property Name -CLike procedimento_*_fs_*_d_*.xml);
$files += @(Get-ChildItem -Path .\procedimentos -Recurse | Where-Object -Property FullName -CLike *\documentos_*_fs_*_d_*);

# exclude directory entries and generate fullpath list
$filesFullPath = $files | Where-Object -Property Attributes -CContains Archive | ForEach-Object -Process {Write-Output -InputObject $_.FullName}

#create zip file
$zipFileName = 'procedimentos.zip'
$zip = [System.IO.Compression.ZipFile]::Open((Join-Path -Path $(Resolve-Path -Path ".") -ChildPath $zipFileName), [System.IO.Compression.ZipArchiveMode]::Create)

#write entries with relative paths as names
foreach ($fname in $filesFullPath) {
    $rname = $(Resolve-Path -Path $fname -Relative) -replace '\.\\',''
    echo $rname
    $zentry = $zip.CreateEntry($rname)
    $zentryWriter = New-Object -TypeName System.IO.BinaryWriter $zentry.Open()
    $zentryWriter.Write([System.IO.File]::ReadAllBytes($fname))
    $zentryWriter.Flush()
    $zentryWriter.Close()
}

# clean up
Get-Variable -exclude Runspace | Where-Object {$_.Value -is [System.IDisposable]} | Foreach-Object {$_.Value.Dispose(); Remove-Variable $_.Name};

좀 오래된 쓰레드이지만 요즘 윈도우 10 설치에 기본인 파워쉘 5.1을 통해 zip 파일을 만드는 데 도움이 될 것 같습니다.스크립트를 사용하면 원본 하위 디렉터리 구조를 유지할 수 있을 뿐만 아니라 불필요한 일부 하위 트리/파일을 제외할 수 있습니다.Visual Studio 솔루션의 소스 코드를 보관하는 데 사용하는 방법은 다음과 같습니다.

Write-Output "Zipping Visual Studio solution..."

# top level from where to start and location of the zip file
$path = "C:\TheSolution"
# top path that we want to keep in the source code zip file
$subdir = "source\TheSolution"
# location of the zip file
$ZipFile = "${path}\TheSolution.zip"

# change current directory
Set-Location "$path"

# collecting list of files that we want to archive excluding those that we don't want to preserve
$Files  = @(Get-ChildItem "${subdir}" -Recurse -File | Where-Object {$_.PSParentPath -inotmatch "x64|packages|.vs|Win32"})
$Files += @(Get-ChildItem "${subdir}\packages" -Recurse -File)
$Files += @(Get-ChildItem "${subdir}\.git" -Recurse -File)
$FullFilenames = $files | ForEach-Object -Process {Write-Output -InputObject $_.FullName}

# remove old zip file
if (Test-Path $ZipFile) { Remove-Item $ZipFile -ErrorAction Stop }

#create zip file
Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem
$zip = [System.IO.Compression.ZipFile]::Open(($ZipFile), [System.IO.Compression.ZipArchiveMode]::Create)

# write entries with relative paths as names
foreach ($fname in $FullFilenames) {
    $rname = $(Resolve-Path -Path $fname -Relative) -replace '\.\\',''
    Write-Output $rname
    $zentry = $zip.CreateEntry($rname)
    $zentryWriter = New-Object -TypeName System.IO.BinaryWriter $zentry.Open()
    $zentryWriter.Write([System.IO.File]::ReadAllBytes($fname))
    $zentryWriter.Flush()
    $zentryWriter.Close()
}

# release zip file
$zip.Dispose()

번거로운 mklement0 기술이 저에게 효과가 있었습니다.아래는 폴더가 섞인 다양한 파일 목록을 지원하기 위해 만든 스크립트입니다.

# Compress LFS based files into a zip
# To use
#  1. place this script in the root folder
#  2. modify the contents of $lfsAssetFiles to point to files relative to this root folder
#  3. modify $zipDestination to be where you want the resultant zip to be placed
# based off of https://stackoverflow.com/a/51394271

# this should match files being .gitignored
$lfsAssetFiles = 
"\Assets\Project\Plugins\x32",
"\Assets\Project\Plugins\x64\HugePlugin.dll"

# This is where the contents of the zip file will be structured, because placing them inside of a specific folder of the zip is difficult otherwise
$zipStruct = $PSScriptRoot + "\zipStruct"

# the actual zip file that will be created
$zipDestination = "C:\Dropbox\GitLfsZip\ProjectNameLfs.zip"

# remove files from previous runs of this script
If(Test-path $zipStruct) {Remove-item $zipStruct -Recurse}
If(Test-path $zipDestination) {Remove-item $zipDestination}

Foreach ($entry in $lfsAssetFiles)
{
  # form absolute path to source each file to be included in the zip
  $sourcePath = $PSScriptRoot + $entry;

  # get the parent directories of the path. If the entry itself is a directory, we still only need the parent as the directory will be created when it is copied over.
  $entryPath = Split-Path -Parent $entry

  # form what the path will look like in the destination
  $entryPath = $zipStruct + $entryPath

  # ensure the folders to the entry path exist
  $createdPath = New-Item -Force -ItemType Directory $entryPath

  # copy the file or directory
  Copy-Item -Recurse -Force $sourcePath $createdPath
}

# create a zip file https://blogs.technet.microsoft.com/heyscriptingguy/2015/page/59/
Add-Type -AssemblyName "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($zipStruct, $zipDestination)
# Compress-Archive doesn't work here because it includes the "zipStruct" folder: Compress-Archive -Path $zipStruct -DestinationPath $zipDestination

언급URL : https://stackoverflow.com/questions/51392050/compress-archive-and-preserve-relative-paths

반응형