MENU

【備忘録】PowerShellで写真の撮影日時毎にフォルダ仕分けする

★環境
 ベースOS:Windows1
 PowerShell:5.1
 スクリプトの文字コード:UTF-8(BOM付き)

PowerShellを使用して、設置先スクリプト内にあるjpg画像の撮影日時(Exif)を使用して、フォルダ作成(例. 241219)を行い、そのフォルダに画像(写真)を仕分けていく。

# System.Drawingライブラリを使用するためにアセンブリをロード
Add-Type -AssemblyName System.Drawing

# スクリプトが置かれているフォルダのパスを取得
$folderPath = Split-Path -Parent $MyInvocation.MyCommand.Path

# 出力するCSVファイルのパスを設定
$outputCsv = Join-Path $folderPath "ImageMetadata.csv"

# ファイル名と撮影日時を保存するための配列を準備
$fileData = @()

# 現在のフォルダ内のすべてのJPEGファイルを取得
Get-ChildItem -Path $folderPath -Filter "*.jpg" | ForEach-Object {

    # 現在処理中のファイルオブジェクトを取得
    $file = $_

    try {
        # 画像ファイルをBitmapオブジェクトとして読み込み
        $image = New-Object Drawing.Bitmap($file.FullName)
        
        # 画像のExif情報の中から、撮影日時(ID 36867)を取得
        $propertyItem = $image.PropertyItems | Where-Object { $_.Id -eq 36867 }
        
        # 撮影日時が存在する場合
        if ($propertyItem) {
            # バイト配列で取得される撮影日時をASCII文字列に変換
            $dateTaken = [System.Text.Encoding]::ASCII.GetString($propertyItem.Value).TrimEnd([char]0)
            
            # 日付を"yymmdd"形式に変換(例: "2024:12:08 12:02:35" → "241208")
            # yyyy:MM:dd の形式を 2桁の年 (yy)、月 (MM)、日 (dd) の順に変換
            $folderName = $dateTaken.Substring(2,2) + $dateTaken.Substring(5,2) + $dateTaken.Substring(8,2)

            # 仕分け先フォルダのパスを設定
            $destinationFolder = Join-Path $folderPath $folderName

            # フォルダが存在しなければ作成
            if (-not (Test-Path -Path $destinationFolder)) {
                New-Item -ItemType Directory -Path $destinationFolder | Out-Null
            }
            
            # メモリ上の画像リソースを解放
            $image.Dispose()
            
            # 画像ファイルを仕分け先フォルダに移動
            $destinationFile = Join-Path $destinationFolder $file.Name
            Move-Item -Path $file.FullName -Destination $destinationFile
            
            # 結果を配列に追加
            $fileData += [PSCustomObject]@{
                FileName   = $file.Name
                DateTaken  = $dateTaken
                FolderName = $folderName
            }
        } else {
            # 撮影日時が存在しない場合
            $image.Dispose()

            $fileData += [PSCustomObject]@{
                FileName   = $file.Name
                DateTaken  = "Exif情報なし"
                FolderName = "不明"
            }
        }

    } catch {
        # エラー発生時にエラーメッセージを表示
        Write-Host "エラー発生: $($_.Exception.Message)"

        # 結果を配列に追加
        $fileData += [PSCustomObject]@{
            FileName   = $file.Name
            DateTaken  = "取得失敗"
            FolderName = "エラー"
        }
    }
}

# 収集したファイル情報をCSV形式で出力
$fileData | Export-Csv -Path $outputCsv -NoTypeInformation -Encoding UTF8

# 処理完了のメッセージを表示
Write-Host "CSVファイルが作成されました: $outputCsv"
Write-Host "画像の仕分けが完了しました。"

仕分けた画像を元に戻したい場合、以下の移動差し戻しスクリプトを実行する。

# スクリプトが実行されたディレクトリを取得
$scriptDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path

# 現在のディレクトリ内のすべてのフォルダを検索(サブフォルダを除く)
$folders = Get-ChildItem -Path $scriptDirectory -Directory

# 各フォルダ内の.jpg画像を取得し、スクリプトディレクトリに移動する
foreach ($folder in $folders) {
    # フォルダ内の.jpg画像を取得
    $jpgFiles = Get-ChildItem -Path $folder.FullName -Filter *.jpg

    foreach ($file in $jpgFiles) {
        try {
            # 画像ファイルをスクリプトディレクトリに移動
            $destinationPath = Join-Path -Path $scriptDirectory -ChildPath $file.Name

            # もし同じ名前のファイルが存在すれば、ファイル名に番号を付けて重複を避ける
            $counter = 1
            while (Test-Path $destinationPath) {
                $newFileName = "{0}_{1}{2}" -f [System.IO.Path]::GetFileNameWithoutExtension($file.Name), $counter, $file.Extension
                $destinationPath = Join-Path -Path $scriptDirectory -ChildPath $newFileName
                $counter++
            }

            # ファイルを移動
            Move-Item -Path $file.FullName -Destination $destinationPath
            Write-Host "Moved: $($file.FullName) to $destinationPath"
        }
        catch {
            Write-Host "Error moving file $($file.FullName): $_"
        }
    }
}

Write-Host "All files have been moved."
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

目次