【问题标题】:Compress-Archive handle files with same name in Powershell在 Powershell 中压缩存档处理具有相同名称的文件
【发布时间】:2020-04-07 21:32:20
【问题描述】:

我正在编写一个存档脚本,它将所需文件收集到一个数组中,然后将它们逐个添加到存档中。

当存在 DIR1/file.ext 和 DIR2/file.ext 时,我遇到了问题,因为 DIR2 的文件将覆盖以前的文件。

如何设置唯一的文件名或如何即时解决它,而不是将文件复制到具有结构的目录然后压缩整个目录?

这是我的代码:

# GET FILE LIST
$outgoingfiles =  Get-ChildItem -Depth 1 -Filter "*.EXT" | Where-Object { $_.DirectoryName -like "*OUTGOING*" }

# Handle if OUTGOING/archive dir is exists
if(-not (Test-Path "OUTGOING/archive")) {
       New-Item -Path "OUTGOING/archive" -ItemType Directory 
}

# ZIP outgoing files
ForEach ($outgoing in $outgoingfiles) {
    Compress-Archive $outgoing.FullName -Update -DestinationPath $zippath
}

谢谢!

【问题讨论】:

  • 文件名是否重要 - 例如。需要保存吗?
  • 所以据我了解,您希望将所有同名文件复制到一个平面目录而不保留文件夹,但要确保文件不会相互覆盖。
  • 必须保留原始文件名,但可以扩展例如原始父目录,因此 DIR1\file.ext 可以是存档中的 dir1_file.ext。在存档中保留目录也很好。
  • 我猜另一种方法是在文件名中嵌入时间戳,但这可能有风险,因为可能同时创建了两个文件。
  • 如何在此代码中操作存档中的文件名? Compress-Archive $outgoing.FullName -Update -DestinationPath $zippath

标签: powershell


【解决方案1】:

当同名文件已包含在 zip 中时,我认为没有办法告诉 Compress-Archive 重命名文件。

您可以做的是创建一个临时文件夹,将所有文件复制到那里,并在需要时重命名它们。然后使用该文件夹中的唯一文件创建 zip 文件。 最后,再次删除临时文件夹:

$zippath  = 'D:\Test\OutGoing.zip'  # path and filename for the output zip file
$rootPath = 'D:\Test'               # where the files can be found

# create a temporary folder to uniquely copy the files to
$tempFolder = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ([Guid]::NewGuid().Guid)
$null = New-Item -ItemType Directory -Path $tempFolder
# create a hashtable to store the fileHash already copied
$fileHash = @{}

# get the list of files and copy them to a temporary folder
Get-ChildItem -Path $rootPath -Depth 1 -Filter '*.EXT' -File | Where-Object { $_.DirectoryName -like "*OUTGOING*" } | ForEach-Object {
    $count = 1
    $newName = $_.Name
    # test if the file name is already in the hash and if so, append a counter to the basename
    while ($fileHash.ContainsKey($newName)) {
        $newName = "{0}({1}){2}" -f $_.BaseName, $count++, $_.Extension
    }
    # store this file name in the hash and copy the file
    $fileHash[$newName] = $true
    $newFile = Join-Path -Path $tempFolder -ChildPath $newName
    $_ | Copy-Item -Destination $newFile -Force
}

# append '*.*' to the temporary folder name.
$path = Join-Path -Path $tempFolder -ChildPath '*.*'
# next, get the list of files in this temp folder and start archiving
Compress-Archive -Path $path -DestinationPath $zippath -Update

# when done, remove the tempfolder and files
Remove-Item -Path $tempFolder -Force -Recurse

希望有帮助

【讨论】:

  • 我喜欢这个答案。展示如何使文件名唯一,如果我的 lazier 方法不够用,这是一个很好的方法。 +1
【解决方案2】:

我只需将文件及其父目录复制到目标文件夹,然后使用Compress-Archive 将其压缩。然后您不必担心文件名的唯一性。

演示:

$sourceFolder = "C:\\"
$destinationFolder = "C:\\OUTGOING"

# Create destination folder if it doesn't exist
if (-not(Test-Path -Path $destinationFolder -PathType Container))
{
    New-Item -Path $destinationFolder -ItemType Directory
}

# Get all .exe files one level deep
$files = Get-ChildItem -Path $sourceFolder -Depth 1 -Filter *.ext

foreach ($file in $files)
{
    # Get standalone parent directory e.g. DIR1, DIR2
    $parentFolder = Split-Path -Path (Split-Path -Path $file.FullName) -Leaf

    # Create destination path with this parent directory
    $destination = Join-Path -Path $destinationFolder -ChildPath $parentFolder

    # Create destination parent directory if it doesn't exist
    if (-not(Test-Path -Path $destination -PathType Container))
    {
        New-Item -Path $destination -ItemType Directory
    }

    # Copy file to parent directory in destination
    Copy-Item -Path $file.FullName -Destination $destination
}

# Zip up destination folder
# Make sure to pass -Update for redoing compression
Compress-Archive -Path $destinationFolder -DestinationPath "OUTGOING.zip" -Update -CompressionLevel Optimal

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多