如何用PowerShell拆分并重新写入.tif文件的IPTC关键词?
Got it, let's get those messed-up TIFF keywords sorted out! PowerShell doesn't have native, out-of-the-box support for IPTC metadata, but we've got two solid approaches here—one using a reliable third-party tool (my go-to) and another using .NET classes if you want to avoid external tools.
Option 1: Use ExifTool (Recommended)
ExifTool is a powerful, free metadata editor that handles IPTC (and pretty much every other metadata standard) flawlessly. It's way simpler than rolling your own solution with .NET.
Step 1: Install ExifTool
- If you use Chocolatey, run this in an elevated PowerShell window:
choco install exiftool - Alternatively, download the standalone executable from the official site, extract it, and add its folder to your system PATH (or just use the full path to
exiftool.exein the script below).
Step 2: PowerShell Script to Split and Re-Write Keywords
This script will loop through all TIFFs in your target folder, split the merged keyword string, and write them back as individual IPTC keywords.
# Replace with your TIFF folder path $targetFolder = "C:\Your\TIFF\Folder\Path" # Set the delimiter that's separating your merged keywords (e.g., ", ", "; ", " | ") $keywordDelimiter = ", " # Grab all TIFF files in the folder $tiffFiles = Get-ChildItem -Path $targetFolder -Filter "*.tif" -File foreach ($file in $tiffFiles) { Write-Host "Processing: $($file.Name)" # Read the current merged keyword string from IPTC $currentKeywords = & exiftool -s3 -Keywords $file.FullName if (-not [string]::IsNullOrEmpty($currentKeywords)) { # Split the string, trim whitespace, and filter out empty entries $splitKeywords = $currentKeywords -split $keywordDelimiter | ForEach-Object { $_.Trim() } | Where-Object { $_ } if ($splitKeywords.Count -gt 0) { # Write the split keywords back to the file (ExifTool auto handles IPTC multi-keyword format) & exiftool "-Keywords=$($splitKeywords -join ', ')" $file.FullName # Clean up the backup file ExifTool creates (remove this line if you want to keep backups!) Remove-Item -Path "$($file.FullName)_original" -Force -ErrorAction SilentlyContinue Write-Host "✅ Updated keywords for $($file.Name)" } else { Write-Host "⚠️ No valid keywords left after splitting for $($file.Name)" } } else { Write-Host "ℹ️ No keywords found in $($file.Name)" } } Write-Host "`nProcessing finished!"
Key Notes:
- Adjust
$keywordDelimiterto match whatever character(s) are separating your merged keywords (common ones are commas, semicolons, or pipes). - ExifTool creates a backup file by default (e.g.,
image.tif_original). The script deletes it automatically, but you can remove thatRemove-Itemline if you want to keep backups.
Option 2: Use .NET's System.Drawing (No External Tools)
If you prefer not to install third-party software, you can use .NET's built-in imaging classes. This is more complex and has some caveats (like handling encoding inconsistencies), but it works for basic cases.
Add-Type -AssemblyName System.Drawing $targetFolder = "C:\Your\TIFF\Folder\Path" $keywordDelimiter = ", " $tiffFiles = Get-ChildItem -Path $targetFolder -Filter "*.tif" -File foreach ($file in $tiffFiles) { Write-Host "Processing: $($file.Name)" $bitmap = [System.Drawing.Bitmap]::FromFile($file.FullName) try { # Find the existing IPTC Keywords property (ID 0x0250) $existingKeywordItems = $bitmap.PropertyItems | Where-Object { $_.Id -eq 0x0250 } if ($existingKeywordItems) { # Decode the merged keyword string (assumes UTF-8 encoding; adjust if needed) $currentKeywords = [System.Text.Encoding]::UTF8.GetString($existingKeywordItems[0].Value).TrimEnd([char]0) if (-not [string]::IsNullOrEmpty($currentKeywords)) { $splitKeywords = $currentKeywords -split $keywordDelimiter | ForEach-Object { $_.Trim() } | Where-Object { $_ } if ($splitKeywords.Count -gt 0) { # Keep all non-keyword metadata properties $nonKeywordItems = $bitmap.PropertyItems | Where-Object { $_.Id -ne 0x0250 } $newPropertyItems = $nonKeywordItems.Clone() # Add each split keyword as a separate IPTC entry foreach ($kw in $splitKeywords) { $newItem = $bitmap.PropertyItems[0].Clone() $newItem.Id = 0x0250 $newItem.Type = 2 # String data type $kwBytes = [System.Text.Encoding]::UTF8.GetBytes($kw + [char]0) $newItem.Value = $kwBytes $newItem.Len = $kwBytes.Length $newPropertyItems += $newItem } # Apply the updated metadata and save the file $bitmap.SetPropertyItems($newPropertyItems) $bitmap.Save($file.FullName, [System.Drawing.Imaging.ImageFormat]::Tiff) Write-Host "✅ Updated keywords for $($file.Name)" } else { Write-Host "⚠️ No valid keywords left after splitting for $($file.Name)" } } else { Write-Host "ℹ️ No keywords found in $($file.Name)" } } else { Write-Host "ℹ️ No IPTC Keywords property exists in $($file.Name)" } } finally { # Always dispose the bitmap to free up resources $bitmap.Dispose() } } Write-Host "`nProcessing finished!"
Caveats for the .NET Approach:
- Encoding can be hit-or-miss: Some TIFFs might use ASCII instead of UTF-8 for IPTC data. If you see garbled text, replace
[System.Text.Encoding]::UTF8with[System.Text.Encoding]::ASCII. - This might overwrite other TIFF metadata if not handled carefully, whereas ExifTool preserves all other metadata by default.
内容的提问来源于stack exchange,提问作者Rico Komenda

