2

我将是第一个承认 PowerShell 不是我的强项的人,但是在互联网上挖掘了一晚上之后,我拼凑了以下内容。最终目标是通过 DateTaken 组织大量的图像驱动器,以及如果存在的 sidecar XMP 文件。它可能不是最优雅的代码,但它几乎可以工作。

最后一个我想不通的问题是,无论扩展名如何,foreach 循环每个文件名只执行一次。例如,只会处理 DSC00001.arw、DSC00001.xmpDSC00001.jpg。

任何正确方向的观点将不胜感激。

谢谢!

$Folders = (Get-ChildItem -Path F:\ -Recurse -Directory -Force).FullName

$objShell  = New-Object -ComObject Shell.Application
$Folders | % {

    $objFolder = $objShell.namespace($_)
    foreach ($File in $objFolder.items()) { 
            if (($File | Split-Path -Extension) -in ".arw",".gif",".tiff",".jpg",".png",".nef") {
                Write-Host $File.Name`t -NoNewline -ForegroundColor Green
                try {
                    $DateTaken = ($objFolder.getDetailsOf($File,12) -replace [char]8206)  -replace [char]8207
                    $DateTaken = [DateTime]::ParseExact($DateTaken, "g", $null)
                    $Year = $DateTaken.ToString('yyyy')
                    $Date = $DateTaken.ToString('yyyy-MM-dd')
                    Write-Host $Date`t -ForegroundColor Blue -NoNewline
                }
                catch {
                    $Year = 'Other'
                    $Date = 'Other'
                    Write-Host $Date`t -ForegroundColor DarkRed -NoNewline
                }
                finally {
                    $DatePath = (Join-Path (Join-Path F:\ $Year ) $Date)
                }
                write-Host $File.Path -> (Join-Path $DatePath ($File | Split-Path -Leaf))-NoNewline
                #Move-Item $File.Path (Join-Path $DatePath ($File | Split-Path -Leaf))
                Write-Host Completed`n -NoNewline

                if (Test-Path (Join-Path ($File | Split-Path) (($File | Split-Path -LeafBase) + '.xmp'))) {
                    Write-Host XMP:`t -ForegroundColor Magenta -NoNewLine
                    Write-Host (Join-Path ($File | Split-Path) (($File | Split-Path -LeafBase) + '.xmp')) -> (Join-Path ($DatePath) (($File | Split-Path -LeafBase) + '.xmp'))
                    #Move-Item (Join-Path ($File | Split-Path) (($File | Split-Path -LeafBase) + '.xmp')) (Join-Path ($DatePath) (($File | Split-Path -LeafBase) + '.xmp'))
                }
            }else {
                Write-Host $File.Name is not an image `n -NoNewline -ForegroundColor DarkYellow    
            }
    }

}
4

1 回答 1

1

我不确定为什么$objFolder.items()实际上没有返回所有预期的文件,但我建议使用 PowerShell 的内置文件系统提供程序来发现每个文件夹中的实际文件,然后用于$objFolder.ParseName()获取可以传递给的参考GetDetailsOf()

$Folders = (Get-ChildItem -Path F:\ -Recurse -Directory -Force).FullName

$objShell  = New-Object -ComObject Shell.Application
$Folders | % {

    $objFolder = $objShell.NameSpace($_)

    foreach ($FileInfo in Get-ChildItem -LiteralPath $_ -File -Force) { # <-- trick is right here, use Get-ChildItem to discover the files in the folder
        if($FileInfo.Extension -in ".arw",".gif",".tiff",".jpg",".png",".nef"){
            $File = $objFolder.ParseName($FileInfo.Name)                # <-- here we resolve the corresponding file item with shell app
    
            # ... resolve and parse dateTaken here, just like before

            # *.xmp file path might be easier to construct like this
            $xmpPath = $FileInfo.FullName -replace "$($FileInfo.Extension)`$",'.xmp'
            if(Test-Path -LiteralPath $xmpPath){
                 # ...
            }
        }
    }
}
于 2020-09-11T22:38:19.940 回答