Powershell script to set original create picture date

Hi Nextcloud Community,

I created a simple PowerShell script that automatically sets the creation, modification, and last access dates of photos from their EXIF metadata.
It works with JPG, JPEG, PNG, TIF, TIFF, no external tools needed.

Key features:

  • Batch process entire folders.
  • Manual folder path entry.
  • No ExifTool required.
  • Runs on Windows PowerShell 5.1. (Windows default)
<#
.SYNOPSIS
    Updates the creation, modification, and last access dates of photo files
    from their original EXIF date ("DateTimeOriginal" or "DateTaken") without using ExifTool.

.DESCRIPTION
    This PowerShell script reads EXIF metadata directly using .NET (System.Drawing)
    to extract the capture date, then applies that date to the file attributes.
    Supports JPG, JPEG, PNG, TIF, and TIFF formats.

.AUTHOR
DX90

.REQUIREMENTS
    - PowerShell 5.1 or higher
    - .NET System.Drawing library available (default on Windows)
#>

# -------------------------------
# Main Script
# -------------------------------
Add-Type -AssemblyName System.Drawing

# Request the path
$Path = Read-Host "đź“‚ Enter the full path of the folder containing the photos"

if (-not (Test-Path $Path)) {
    Write-Host "❌ The path '$Path' was not found."
    exit
}

# Include subfolders?
$RecurseInput = Read-Host "Include subfolders? (y/n)"
if ($RecurseInput -eq "y" -or $RecurseInput -eq "Y") {
    $Recurse = $true
} else {
    $Recurse = $false
}

# Extensions to search for
$extensions = ".jpg", ".jpeg", ".png", ".tif", ".tiff"

Write-Host "`n🔍 Searching for files in $Path..."

# Get files ignoring case
$files = Get-ChildItem -Path $Path -Recurse:$Recurse -File | Where-Object { $extensions -contains $_.Extension.ToLower() }

if ($files.Count -eq 0) {
    Write-Host "⚠️ No photo files found in this folder."
    exit
}

foreach ($file in $files) {
    try {
        # Read the image to get EXIF date
        $image = [System.Drawing.Image]::FromFile($file.FullName)
        $propItem = $image.GetPropertyItem(36867)  # DateTimeOriginal

        if ($propItem) {
            $dateString = [System.Text.Encoding]::ASCII.GetString($propItem.Value).Trim()
            $dateString = $dateString -replace "\0",""
            $dateTaken = [datetime]::ParseExact($dateString, "yyyy:MM:dd HH:mm:ss", $null)

            # Release the image
            $image.Dispose()

            # Apply dates
            Set-ItemProperty -LiteralPath $file.FullName -Name CreationTime -Value $dateTaken
            Set-ItemProperty -LiteralPath $file.FullName -Name LastWriteTime -Value $dateTaken
            Set-ItemProperty -LiteralPath $file.FullName -Name LastAccessTime -Value $dateTaken

            Write-Host "✅ $($file.Name) → date updated: $dateTaken"
        } else {
            $image.Dispose()
            Write-Host "⚠️ No EXIF date for: $($file.Name)"
        }
    }
    catch {
        Write-Host "❌ Error with $($file.Name): $_"
    }
}

Write-Host "`nâś… Script completed."
pause

And french version :

<#
.SYNOPSIS
    Met à jour les dates de création, de modification et de dernier accès des fichiers photo
    Ă  partir de la date EXIF originale ("DateTimeOriginal" ou "DateTaken") sans utiliser ExifTool.

.DESCRIPTION
    Ce script PowerShell lit les métadonnées EXIF directement à l’aide de .NET (System.Drawing)
    pour extraire la date de prise de vue, puis applique cette date aux attributs du fichier.
    Compatible avec les formats JPG, JPEG, PNG, TIF et TIFF.

.AUTEUR
DX90

.PRÉREQUIS
    - PowerShell 5.1 ou supérieur
    - Bibliothèque .NET System.Drawing disponible (par défaut sur Windows)
#>

# -------------------------------
# Script principal
# -------------------------------

Add-Type -AssemblyName System.Drawing

# Demande du chemin
$Path = Read-Host "đź“‚ Entrez le chemin complet du dossier contenant les photos"

if (-not (Test-Path $Path)) {
    Write-Host "❌ Le chemin '$Path' est introuvable."
    exit
}

# Inclure les sous-dossiers ?
$RecurseInput = Read-Host "Inclure les sous-dossiers ? (o/n)"
if ($RecurseInput -eq "o" -or $RecurseInput -eq "O") {
    $Recurse = $true
} else {
    $Recurse = $false
}

# Extensions recherchées
$extensions = ".jpg", ".jpeg", ".png", ".tif", ".tiff"

Write-Host "`n🔍 Recherche des fichiers dans $Path..."

# Récupération des fichiers sans problème de casse
$files = Get-ChildItem -Path $Path -Recurse:$Recurse -File | Where-Object { $extensions -contains $_.Extension.ToLower() }

if ($files.Count -eq 0) {
    Write-Host "⚠️ Aucun fichier photo trouvé dans ce dossier."
    exit
}

foreach ($file in $files) {
    try {
        # Lire l'image pour obtenir la date EXIF
        $image = [System.Drawing.Image]::FromFile($file.FullName)
        $propItem = $image.GetPropertyItem(36867)  # DateTimeOriginal

        if ($propItem) {
            $dateString = [System.Text.Encoding]::ASCII.GetString($propItem.Value).Trim()
            $dateString = $dateString -replace "\0",""
            $dateTaken = [datetime]::ParseExact($dateString, "yyyy:MM:dd HH:mm:ss", $null)

            # Libérer l'image
            $image.Dispose()

            # Appliquer les dates
            Set-ItemProperty -LiteralPath $file.FullName -Name CreationTime -Value $dateTaken
            Set-ItemProperty -LiteralPath $file.FullName -Name LastWriteTime -Value $dateTaken
            Set-ItemProperty -LiteralPath $file.FullName -Name LastAccessTime -Value $dateTaken

            Write-Host "✅ $($file.Name) → date mise à jour : $dateTaken"
        } else {
            $image.Dispose()
            Write-Host "⚠️ Pas de date EXIF pour : $($file.Name)"
        }
    }
    catch {
        Write-Host "❌ Erreur avec $($file.Name) : $_"
    }
}

Write-Host "`n✅ Script terminé."
pause

To conserve icons in script, you must save and use UTF8 BOM

Perfect for keeping photo timestamps correct afer downloading from Nextcloud.

I’d like to hear your thoughts, feedback, or suggestions for improving this tool.

Thank’s

1 Like