【问题标题】:Extract file from zips in sub folders从子文件夹中的 zip 中提取文件
【发布时间】:2019-09-12 14:02:57
【问题描述】:

我对 PowerShell 比较陌生,只在编写“轻量级”脚本来自动执行一些工作任务。

大多数时候,我可以通过谷歌搜索得到我需要的答案,也许还需要一些小的调整/实验。

但是我需要一些帮助,因为我找不到我正在寻找的答案,所以希望这里的人可以帮助我。

详情:

我在网络驱动器上获得了指向包含“.zips”的子文件夹或仅包含“.zips”的文件夹的目录链接。

后一种情况适用于我当前的脚本(将在下面提供)来完成它的工作,但前一种情况是我苦苦挣扎的地方。

TL;DR - 我需要脚本进入每个文件夹,将每个“.zip”解压缩到“临时”文件夹中,然后查找“备份”图像文件(文件类型可能会有所不同),然后将其复制出来到子文件夹并重命名为与提取它的“.zip”相同的名称。

再一次,如果我实际位于包含“.zip”文件的文件夹中,但如果“.zip”文件位于子文件夹中,则我的脚本有效,因为我无法将其递归地放入每个文件夹中并且运行脚本。

示例设置:

文件夹A\文件夹B\1.zip

文件夹A\文件夹B\2.zip

文件夹A\文件夹B\3.zip

文件夹A\文件夹C\1.zip

文件夹A\文件夹C\1.zip

文件夹A\文件夹C\1.zip

下面的脚本:

#Current Directory of ".zip" files
$fileLocation = read-host "Type/Paste location of creatives"

#replace server path with drive letter
if (Test-Path \\server\path\* -PathType Leaf) {
    $serverPathName = "\\server\path\"
    $driveLetter = "D:\"
    $fileLocation = ($fileLocation -replace [regex]::Escape($serverPathName),$driveLetter)
}
$fileLocation = Resolve-Path $fileLocation
Write-Output $fileLocation

#change directory to the one provided
$zipFilesPath = cd "$fileLocation"
$currentDirectory = pwd

#File type of backup
#Note: `n = new line
write-host "`nChoose Creative Backup File Type"
Write-Host "1. JPG"
Write-host "2. JPEG"
Write-Host "3. PNG"
Write-Host "4. GIF"

$typeFilter = Read-Host "`nType? 1/2/3/4"
if($typeFilter -eq '1'){
    $typeFilter = 'jpg'
}
elseif($typeFilter -eq '2'){
    $typeFilter = 'jpeg'
}
elseif($typeFilter -eq '3'){
    $typeFilter = 'png'
}
elseif($typeFilter -eq '4'){
    $typeFilter = 'gif'
}
else {
    write-host "ERROR! Incorrect Input!"
    Write-Host "Exiting Script..."
    start-sleep -seconds 1.5
    Exit
}

#Files Location
$ZipFilesPath = "$currentDirectory\*.zip"

#Unzip To Same Location
$UnzipPath = "$currentDirectory"

#Check if Temp Folder exists
$TempCheck = Test-Path "$currentDirectory\Temp"

If ($TempCheck -eq $false) {
#Create Temp Folder
New-Item -ItemType directory -Path "$currentDirectory\Temp" -Force
}

$TempPath = "$currentDirectory\Temp"

$Shell = New-Object -com Shell.Application
$Location = $Shell.NameSpace($TempPath)
$ZipFiles = Get-Childitem $ZipFilesPath -Recurse -Include *.ZIP

$FileCounter = 1

#Clear Initilisation Vars from Console
clear

foreach ($ZipFile in $ZipFiles) {
    #Get The Base Filename without the extension
    $ZipFileActualName = [io.path]::GetFileNameWithoutExtension($ZipFile.FullName)

    write-host File:   $ZipFileActualName

    $ZipFolder = $Shell.NameSpace($ZipFile.fullname)
    $Location.Copyhere($ZipFolder.items(), 1040)

    #Find and rename backups

    $BackupFiles = Get-ChildItem $TempPath -Filter *backup*.$typeFilter -Recurse
    $BackupFiles |% {Move-Item $_.Fullname $UnzipPath/$ZipFileActualName'_backup'.$typefilter}

    #Clear Temp Folder
    Get-ChildItem -Path "$currentDirectory\Temp" -Include *.* -File -Recurse | foreach { $_.Delete()}

    #Move Along to Next File
    $FileCounter++
}

#Delete Temp Folder
Remove-Item "$currentDirectory\Temp" -Force -Recurse

#Clear Console
clear
#Read-Host -Prompt “Press Enter to exit”
#start .\

我愿意接受所提供的任何建议或改进领域。如果我需要完全更改代码,我不介意。只要它适用于这两种情况。

谢谢。


更新

按照HAL9256的说明修改脚本:

#Current Directory of creatives
$fileLocation = read-host "Type/Paste location of creatives"

if (Test-Path \\server\path\* -PathType Leaf) {
    $serverPathName = "\\server\path\"
    $driveLetter = "D:\"
    $fileLocation = ($fileLocation -replace [regex]::Escape($serverPathName),$driveLetter)
}
$fileLocation = Resolve-Path $fileLocation
Write-Output $fileLocation

$zipFilesPath = cd "$fileLocation"
$currentDirectory = pwd

#File type of backup
#Note: `n = new line
write-host "`nChoose Creative Backup File Type"
Write-Host "1. JPG"
Write-host "2. JPEG"
Write-Host "3. PNG"
Write-Host "4. GIF"

$typeFilter = Read-Host "`nType? 1/2/3/4"
if($typeFilter -eq '1'){
    $typeFilter = 'jpg'
}
elseif($typeFilter -eq '2'){
    $typeFilter = 'jpeg'
}
elseif($typeFilter -eq '3'){
    $typeFilter = 'png'
}
elseif($typeFilter -eq '4'){
    $typeFilter = 'gif'
}
else {
    write-host "ERROR! Incorrect Input!"
    Write-Host "Exiting Script..."
    start-sleep -seconds 1.5
    Exit
}

#Files Location
$ZipFilesPath = "$currentDirectory"

#Unzip To Same Location
$UnzipPath = "$currentDirectory"

#Check if Temp Folder exists
$TempCheck = Test-Path "$currentDirectory\Temp"

If ($TempCheck -eq $false) {
#Create Temp Folder
New-Item -ItemType directory -Path "$currentDirectory\Temp" -Force
}

$TempPath = "$currentDirectory\Temp"

$Shell = New-Object -com Shell.Application
$Location = $Shell.NameSpace($TempPath)
$ZipFiles = Get-Childitem $ZipFilesPath -Recurse -Include *.ZIP

$FileCounter = 1

#Clear Initilisation Vars from Console
clear

foreach ($ZipFile in $ZipFiles) {
    #Get The Base Filename without the extension
    $ZipFileActualName = [io.path]::GetFileNameWithoutExtension($ZipFile.FullName)

    write-host File:   $ZipFileActualName

    $ZipFolder = $Shell.NameSpace($ZipFile.fullname)
    $Location.Copyhere($ZipFolder.items(), 1040)

    #Find and rename backups

    $BackupFiles = Get-ChildItem $TempPath -Filter *backup*.$typeFilter -Recurse
    $BackupFiles |% {Move-Item $_.Fullname $upzipPath/$ZipFileActualName'_backup'.$typefilter}

    #Clear Temp Folder
    Get-ChildItem -Path "$currentDirectory\Temp" -Include *.* -File -Recurse | foreach { $_.Delete()}

    #Move Along to Next File
    $FileCounter++
}

#Delete Temp Folder
Remove-Item "$currentDirectory\Temp" -Force -Recurse

#Clear Console
clear
#Read-Host -Prompt “Press Enter to exit”
#start .\

这就是我需要做的。但是如何修改我的脚本,以便将备份存储在各自的文件夹中?那么从“FolderB”中提取的备份保留在“FolderB”等中吗?有什么我可以做的吗?


更新 2 最终代码 - 感谢 HAL9256 的帮助:

#Current Directory of creatives
$fileLocation = read-host "Type/Paste location of creatives"

if (Test-Path \\server\path\* -PathType Leaf) {
    $serverPathName = "\\server\path\"
    $driveLetter = "D:\"
    $fileLocation = ($fileLocation -replace [regex]::Escape($serverPathName),$driveLetter)
}
$fileLocation = Resolve-Path $fileLocation
Write-Output $fileLocation

$zipFilesPath = cd "$fileLocation"
$currentDirectory = pwd

#File type of backup
#Note: `n = new line
write-host "`nChoose Creative Backup File Type"
Write-Host "1. JPG"
Write-host "2. JPEG"
Write-Host "3. PNG"
Write-Host "4. GIF"

$typeFilter = Read-Host "`nType? 1/2/3/4"
if($typeFilter -eq '1'){
    $typeFilter = 'jpg'
}
elseif($typeFilter -eq '2'){
    $typeFilter = 'jpeg'
}
elseif($typeFilter -eq '3'){
    $typeFilter = 'png'
}
elseif($typeFilter -eq '4'){
    $typeFilter = 'gif'
}
else {
    write-host "ERROR! Incorrect Input!"
    Write-Host "Exiting Script..."
    start-sleep -seconds 1.5
    Exit
}

#Files Location
$ZipFilesPath = "$currentDirectory"

#Unzip To Same Location
$UnzipPath = "$currentDirectory"

#Check if Temp Folder exists
$TempCheck = Test-Path "$currentDirectory\Temp"

If ($TempCheck -eq $false) {
#Create Temp Folder
New-Item -ItemType directory -Path "$currentDirectory\Temp" -Force
}

$TempPath = "$currentDirectory\Temp"

$Shell = New-Object -com Shell.Application
$Location = $Shell.NameSpace($TempPath)
$ZipFiles = Get-Childitem $ZipFilesPath -Recurse -Include *.ZIP

$FileCounter = 1

#Clear Initilisation Vars from Console
clear

foreach ($ZipFile in $ZipFiles) {
    #Get The Base Filename without the extension
    $ZipFileActualName = [io.path]::GetFileNameWithoutExtension($ZipFile.FullName)

    write-host File:   $ZipFileActualName

    $ZipFolder = $Shell.NameSpace($ZipFile.fullname)
    $Location.Copyhere($ZipFolder.items(), 1040)
    $DestinationDir = $ZipFile.DirectoryName.Replace($ZipFilesPath,$unzipPath)

    #Find and rename backups
    $BackupFiles = Get-ChildItem $TempPath -Filter *backup*.$typeFilter -Recurse
    $BackupFiles |% {Move-Item $_.Fullname $DestinationDir/$ZipFileActualName'_backup'.$typefilter}

    #Clear Temp Folder
    Get-ChildItem -Path "$currentDirectory\Temp" -Include *.* -File -Recurse | foreach { $_.Delete()}

    #Move Along to Next File
    $FileCounter++
}

#Delete Temp Folder
Remove-Item "$currentDirectory\Temp" -Force -Recurse

#Clear Console
clear
#Read-Host -Prompt “Press Enter to exit”
#start .\

【问题讨论】:

    标签: powershell


    【解决方案1】:

    当你指定路径时:

    #Files Location
    $ZipFilesPath = "$currentDirectory\*.zip"
    

    然后尝试获取文件:

    $ZipFiles = Get-Childitem $ZipFilesPath -Recurse -Include *.ZIP
    

    您实际上是在说Get-Childitem 并获取 *.zip 文件。因为路径参数有通配符过滤器,所以它只会获取该目录中的所有*.zip 文件,而不会获取任何文件夹。由于您没有与*.zip 通配符匹配的文件夹,因此Get-Childitem 将没有任何文件夹可以继续递归。

    解决方案是只为Get-Childitem 递归的路径参数提供一个基本文件夹,并且正确地使用-Include 为该类型应用过滤器。例如:

    #Files Location
    $ZipFilesPath = "$currentDirectory"
    
    ...
    
    $ZipFiles = Get-Childitem $ZipFilesPath -Recurse -Include *.ZIP
    

    编辑:

    要将文件移动到相同的文件夹结构,在循环中,您只需使用替换功能将源目录路径(目录名称的第一部分)替换为目标基本路径。然后子文件夹将保持不变。例如

    ...
    
    $DestinationDir = $ZipFile.DirectoryName.Replace($ZipFilesPath,$upzipPath)
    
    ...
    
    $BackupFiles |% {Move-Item $_.Fullname $DestinationDir/$ZipFileActualName'_backup'.$typefilter}
    

    【讨论】:

    • 您好 Hal9256,感谢您的帮助。那做了我需要做的。但是如何修改我的脚本,以便将备份存储在各自的文件夹中?那么从“FolderB”中提取的备份保留在“FolderB”等中吗?有什么我可以做的吗?
    • 移动文件时,您可以简单地将源目录文本替换为目标目录。请参阅上面的修改。
    猜你喜欢
    • 1970-01-01
    • 2012-06-13
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    相关资源
    最近更新 更多