我很难让compress-archive
做我想做的事...
我有一个根项目文件夹,我想压缩子目录中的某些文件并保留相对路径。例如:
/
├── _scripts
├── ├─_module1
| | └── filex.js
| └─_module2
| ├── file1.js
| └── file2.txt
因此,我想从我的根目录创建一个包含module2/*
的zip文件,并且我想保留文件夹结构。我希望我的拉链包含:
scripts/module2/file1.js
scripts/module2/file2.txt
但是当我从根文件夹运行此命令时:
Compress-Archive -Path "scripts\module2\*" -DestinationPath tmp.zip
zip文件的内容仅包含:
/file1.js
/file2.txt
答案 0 :(得分:4)
看来Compress-Archive
(从Windows PowerShell v5.1开始)不支持您想要的内容:
以文件夹为目标,将该文件夹的子树递归地添加到存档中,但仅按目标文件夹的名称(它将成为存档中的子文件夹)添加,而不是其< em>路径。
具体地说,
Compress-Archive -Path scripts\module2 -DestinationPath tmp.zip
(递归)将scripts\module2
的内容存储在tmp.zip
中,但不使用存档内部路径.\scripts\module2
,而仅使用.\module2
-目标文件夹的名称(最后一个输入路径组件)。
含义是,您必须传递文件夹scripts
才能获得所需的存档内部路径,但这总是包含scripts
的 entire子树 ,因为Compress-Archive
没有提供包含/排除机制。
一个麻烦的选项是在$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 + [System.IO.Compression.ZipFile]
class;您可以使用Add-Type -Assembly System.IO.Compression.FileSystem
将其加载到会话中(在PowerShell Core 中不是必需的)。
通过使用诸如7-Zip,
答案 1 :(得分:1)
cumbersome technique mklement0 mentioned为我工作。下面是我创建的脚本,用于支持与文件夹混合的各种文件的列表。
# 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
答案 2 :(得分:0)
我想这样做,而不必将整个结构复制到临时目录中。
#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};
答案 3 :(得分:0)
这是一个有点旧的线程,但是我认为这将帮助人们通过PowerShell 5.1创建zip文件,PowerShell 5.1是当今Windows 10安装的标准配置。脚本允许您保留原始的子目录结构,并排除一些不必要的子树/文件。这是我用来存档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()