使用 Powershell 对 HEIC 文件进行 7zip 压缩,将 7zip 存档命名为直接子文件夹的名称,然后从多个子文件夹中删除 HEIC 文件

Using Powershell to 7zip HEIC files, name the 7zip archive the immediate subfolder's name, and then delete HEIC files from multiple subfolders

全部,

我正在尝试压缩、附加到 zip 名称,然后从多个子文件夹中删除 HEIC 文件。这是一个示例布局:

Years
|2019
||09.01.19 - Visiting the Zoo
|||Photo1.HEIC
|||Photo1.JPG
|||Photo2.HEIC
|||Photo2.JPG
|||Photo3.HEIC
|||Photo3.JPG
|2020
||09.02.20 - Pumpkin Picking
|||DSC01.HEIC
|||DSC01.JPG
|||DSC02.HEIC
|||DSC02.JPG
|||DSC03.HEIC
|||DSC03.JPG
|2021
||09.04.21 - Whitewater Rafting
|||IMG01.HEIC
|||IMG01.JPG
|||IMG02.HEIC
|||IMG02.JPG
|||IMG03.HEIC
|||IMG03.JPG

我想要完成的是:

Years
|2019
||09.01.19 - Visiting the Zoo
|||Photo1.JPG
|||Photo2.JPG
|||Photo3.JPG
|||09.01.19 - Visiting the Zoo(HEIC).7z
|2020
||09.02.20 - Pumpkin Picking
|||DSC01.JPG
|||DSC02.JPG
|||DSC03.JPG
|||09.02.20 - Pumpkin Picking(HEIC).7z
|2021
||09.04.21 - Whitewater Rafting
|||IMG01.JPG
|||IMG02.JPG
|||IMG03.JPG
|||09.04.21 - Whitewater Rafting(HEIC).7z

这是我目前的脚本:

zipPath = "$env:ProgramFiles-Zipz.exe"
if (-not (Test-Path -Path zipPath -PathType Leaf)) {
    throw "7 zip file 'zipPath' not found"
}
Set-Alias 7zip zipPath
$path = "T:\TEST\YEARS"
$dest = "T:\TEST\YEARS"
$mask = "*.HEIC"
$files = dir $path -Recurse -Include $mask 
ForEach ($file in $files) 
    {
     7zip a tzip mx "$dest$($file.basename)HEIC.7z" $file

    }
Get-ChildItem -Path 'T:\TEST\YEARS' $mask -Recurse | foreach { Remove-Item -Path $_.FullName }

上述脚本的问题在于它将压缩文件移动到“T:\TEST\YEARS”并且没有将其留在子文件夹中。此外,它将每个子文件夹加在一起。

由于压缩不起作用,我还没有测试删除 HEIC 文件。

我该如何解决这个问题?

谢谢!

编辑:在另一个论坛上咨询后,这是我最终使用的脚本:

$yearDir = "$PSScriptRoot\YEARS" #changes this.

try {
    $yearDirResults = Get-ChildItem -Path $yearDir -Directory -ErrorAction Stop
}
catch {
    Write-Error $Error[0] -ErrorAction Stop
}

#could've done a another foreach-object for $yearDirResults but thought this would be easier to read..
foreach ($year in $yearDirResults) {
    $compressError = $false #we use this later, make sure it's false for now.
    try {
        #For each 'YEAR' folder (i.e. 2019,2020,2021); get all child-items, no recurse, and create archive of HEIC files..
        Get-ChildItem -Path $year.FullName -Directory -ErrorAction Stop | ForEach-Object {
            #for each sub-directory of "YEAR" (i.e. '2021\whitewater rafting')
            $heicFiles = Test-Path "$($_.FullName)\*" -Include '*.heic' #a simple test to see if our current directory has any HEIC files.
            if ($heicFiles) {
                #looks like we have HEIC files so let's do archive/compression stuff...
                $compressionPath = "$($_.FullName)\*.HEIC" #Compress-Archive uses this for the -Path param of all files to compress.  We can use a wildcard of *.heic.
                $zipName = "$(Split-Path $($_.FullName) -Leaf)(HEIC).zip" # do some string stuff to get the ZIP output file name based on the current directory we're working with.
                $heicZipOutput = Join-Path -Path $($_.FullName) -ChildPath $zipName # join the main folder name along with the zip name to get a full path for DestinationPath param on Compress-Archive.
                "Compressiong $compressionPath and outputting to $heicZipOutput"
                try {
                    #we don't want to delete our HEIC files unless we know Compress-Archvie completed without error so we put it in a try/catch block.
                    #For Compress-Archive I'm using -Update parameter instead of -Force.  Using -Force will overwrite a .zip file with the same name if one already exists.
                    #I think "Update" is a better choice over "Force" because if you ever add any new HEIC files to a directory that already contains a .zip archive then the archive will be updated with new files instead of deleted and only contain the new files.
                    Compress-Archive -Path $compressionPath -DestinationPath $heicZipOutput -Update -CompressionLevel Fastest -ErrorAction Stop #-WhatIf #uncomment the -WhatIf to see what would happen if this was actually run.                    
                }
                catch {
                    $compressError = $true
                    Write-Error $Error[0]
                }

                if($compressError){
                    #Well, there was an error creating the .zip archive so we through a warning and move on..
                    Write-Warning "There was an error creating our archive in $heicZipOutput.  Not deleting any files."
                } else {
                    Write-Warning "Deleting HEIC files from $($_.FullName)"
                    try {
                        Remove-Item -Path "$($_.FullName)\*" -Include '*.heic' -ErrorAction Stop -Force -WhatIf #Remove -WhatIf when ready to actually delete files.
                    }
                    catch {
                        #Unable to remove HEIC files from a folder is an error only for this specific loop case - we use continue to move to next iteration.
                        Write-Error $Error[0] -ErrorAction Continue
                    }
                }
                
            }
            else {
                #Well, looks like $heicFiles was empty (no HEIC files found in current dir) so we just spit out a warning and move on.
                Write-Warning "No HEIC files found in $($_.FullName).  Skipping compression."
            }    
        }
    }
    catch {
        #hopefully we'd never end up here but simple error catching in case Get-ChildItem filed on $year.FullName.
        Write-Error $Error[0] -ErrorAction Stop
    }
}

https://community.spiceworks.com/topic/2331629-using-powershell-to-7zip-heic-files-rename-the-archive-and-delete-files

我认为您尝试的问题在于您实际上并未针对 HEIC 文件所在的目录。看看这是否符合您的预期。

zipPath = "$env:ProgramFiles-Zipz.exe"

if (-not (Test-Path -Path zipPath -PathType Leaf)){
    throw "7 zip file 'zipPath' not found"
}

Set-Alias 7zip $zipPath

$rootpath = "T:\TEST\YEARS"

$mask = "*.HEIC"

$files = Get-ChildItem $rootpath -Recurse -Include $mask -File

foreach ($file in $files){
    Write-Host "Processing '$($file.FullName)'" -ForegroundColor Cyan

    Push-Location $file.PSParentPath

    $zip = "$(Split-Path $file.PSParentPath -Leaf)(HEIC).7z"

    $null = 7zip a $zip $file

    if($?){
        Write-Host "Successfully added '$($file.FullName)' to '$zip'" -ForegroundColor Green
        Remove-Item $file
    }
    else{
        Write-Warning "Error adding '$($file.FullName)' to '$zip'"
    }

    Pop-Location
}

在与另一个论坛核对后,这里是我最终使用的脚本:

https://community.spiceworks.com/topic/2331629-using-powershell-to-7zip-heic-files-rename-the-archive-and-delete-files

$yearDir = "$PSScriptRoot\YEARS" #changes this.

try {
    $yearDirResults = Get-ChildItem -Path $yearDir -Directory -ErrorAction Stop
}
catch {
    Write-Error $Error[0] -ErrorAction Stop
}

#could've done a another foreach-object for $yearDirResults but thought this would be easier to read..
foreach ($year in $yearDirResults) {
    $compressError = $false #we use this later, make sure it's false for now.
    try {
        #For each 'YEAR' folder (i.e. 2019,2020,2021); get all child-items, no recurse, and create archive of HEIC files..
        Get-ChildItem -Path $year.FullName -Directory -ErrorAction Stop | ForEach-Object {
            #for each sub-directory of "YEAR" (i.e. '2021\whitewater rafting')
            $heicFiles = Test-Path "$($_.FullName)\*" -Include '*.heic' #a simple test to see if our current directory has any HEIC files.
            if ($heicFiles) {
                #looks like we have HEIC files so let's do archive/compression stuff...
                $compressionPath = "$($_.FullName)\*.HEIC" #Compress-Archive uses this for the -Path param of all files to compress.  We can use a wildcard of *.heic.
                $zipName = "$(Split-Path $($_.FullName) -Leaf)(HEIC).zip" # do some string stuff to get the ZIP output file name based on the current directory we're working with.
                $heicZipOutput = Join-Path -Path $($_.FullName) -ChildPath $zipName # join the main folder name along with the zip name to get a full path for DestinationPath param on Compress-Archive.
                "Compressiong $compressionPath and outputting to $heicZipOutput"
                try {
                    #we don't want to delete our HEIC files unless we know Compress-Archvie completed without error so we put it in a try/catch block.
                    #For Compress-Archive I'm using -Update parameter instead of -Force.  Using -Force will overwrite a .zip file with the same name if one already exists.
                    #I think "Update" is a better choice over "Force" because if you ever add any new HEIC files to a directory that already contains a .zip archive then the archive will be updated with new files instead of deleted and only contain the new files.
                    Compress-Archive -Path $compressionPath -DestinationPath $heicZipOutput -Update -CompressionLevel Fastest -ErrorAction Stop #-WhatIf #uncomment the -WhatIf to see what would happen if this was actually run.                    
                }
                catch {
                    $compressError = $true
                    Write-Error $Error[0]
                }

                if($compressError){
                    #Well, there was an error creating the .zip archive so we through a warning and move on..
                    Write-Warning "There was an error creating our archive in $heicZipOutput.  Not deleting any files."
                } else {
                    Write-Warning "Deleting HEIC files from $($_.FullName)"
                    try {
                        Remove-Item -Path "$($_.FullName)\*" -Include '*.heic' -ErrorAction Stop -Force -WhatIf #Remove -WhatIf when ready to actually delete files.
                    }
                    catch {
                        #Unable to remove HEIC files from a folder is an error only for this specific loop case - we use continue to move to next iteration.
                        Write-Error $Error[0] -ErrorAction Continue
                    }
                }
                
            }
            else {
                #Well, looks like $heicFiles was empty (no HEIC files found in current dir) so we just spit out a warning and move on.
                Write-Warning "No HEIC files found in $($_.FullName).  Skipping compression."
            }    
        }
    }
    catch {
        #hopefully we'd never end up here but simple error catching in case Get-ChildItem filed on $year.FullName.
        Write-Error $Error[0] -ErrorAction Stop
    }
}

非常感谢所有帮助过我的人。即使我没有使用您的解决方案,我仍然感谢您付出的时间和精力。