JadonR
JadonR

Reputation: 193

Powershell - change file Date Created and Date Modified based on Filename

I have lots of file scanned PDF documents that have the file named with an included date. For example:

FileA_2017-10-15.pdf
FileB_2016-04-08.pdf
FileC_2018-01-30.pdf

some files also are formatted with an underscore at the end as well such as...

FileD_2018-01-30_1.pdf
FileE_2018-01-30_2.pdf

there are even a few that have two underscores before the date such as...

FileF_Example_2018-01-30_1.pdf
FileG_Example_2018-01-30_2.pdf

Unfortunately, the date they were scanned in is different than the actual date of the document. So the "Date Created" and "Date Modified" attributes are different than what is shown in the file name.

I would like a script that I could run to change the "Date Created" and "Date Modified" to match that of the filename.

I attempted this using someone else's script but I don't know enough about PowerShell to make it actually work. Note that I do not want to change the name of the file, only the time stamp.

$Directory = "C:\TestFolder"
$DateFormat = "yyyy-MM-dd"


foreach ($file in (Get-ChildItem $Directory)) {
    $date_from_file=GetFileName::[datetime])

    $file.CreationTime = $date_from_file
    $file.LastAccessTime = $date_from_file
    $file.LastWriteTime = $date_from_file

    Write-Host ($file.Name + " - " + $date_from_file)
    }

The code above can be scraped if something else has already been written since what I have doesn't work.

Edit Wondering if it would also be possible to add to the script so that it could include files in sub-folders as well. Maybe it could be scripted in a way that would only consider the files in a folder if the Date Modified on the folder is today. I would like to run this on a parent folder that could potentially have many sub-folders and if those folders don't have a "Date Modified" of today, then it should skip the files in that folder. I was thinking that could speed up the process. Open to thoughts and thanks for the help!

Upvotes: 1

Views: 13748

Answers (3)

hydra3333
hydra3333

Reputation: 177

Thanks. I was stuck without this thread. I ended up with a variation that matched any filename with a correctly formatted date, thus:

# Call like:
#   powershell -NoLogo -ExecutionPolicy Unrestricted -Sta -NonInteractive -WindowStyle Normal -File ".\Rename_files_selected_folders_ModifyDateStamps.ps1" -Folder "T:\files" 
# 1. capture a commandline parameter 1 as a mandatory "Folder string" with a default value 
param ( [Parameter(Mandatory=$true)] [string]$Folder = "T:\HDTV\autoTVS-mpg\Converted" ) 
[console]::BufferWidth = 512 
$DateFormat = "yyyy-MM-dd" 
write-output "Processing Folder: ",$Folder  
# 2. Iterate the files 
$FileList = Get-ChildItem -Recurse $Folder -Include '*.mp4','*.bprj','*.ts' -File 
foreach ($FL_Item in $FileList) { 
    $ixxx = $FL_Item.BaseName -match '(?<DateString>\d{4}-\d{2}-\d{2})' 
    if($ixxx){ 
        #write-output $FL_Item.FullName 
        $DateString = $Matches.DateString 
        $date_from_file = [datetime]::ParseExact($DateString, $DateFormat, $Null) 
        $FL_Item.CreationTime = $date_from_file 
        $FL_Item.LastWriteTime = $date_from_file 
        $FL_Item | Select-Object FullName,CreationTime,LastWriteTime 
    } 
} 
# https://stackoverflow.com/questions/56211626/powershell-change-file-date-created-and-date-modified-based-on-filename 

Upvotes: 0

Lee_Dailey
Lee_Dailey

Reputation: 7489

[ edit - since the OP is getting very strange errors with my suggested fix - errors that i cannot reproduce with the sample data - i've changed this answer to the full suggested code. edit 2 - added new file name variants and code to deal with them.
edit 3 - changed from splitting to a regex match since the sample data has changed yet again. [*sigh ...*] ]

you are not actually creating the datetime object that you need. the $date_from_file= line doesn't actually do anything other than create red error msgs ... [grin]

replace this line ...

$date_from_file=GetFileName::[datetime])

... with this line ...

$date_from_file = [datetime]::ParseExact($File.BaseName.Split('_')[-1], $DateFormat, $Null)

... and your $date_from_file variable will contain a proper [datetime] object that will work in your assignments.

i would likely change the sequence of those assignments to put the $file.LastAccessTime = $date_from_file LAST so that it doesn't get changed by the next line.

also, that value will change any time that the file is accessed, so it may not be worth changing. [grin]


here is the full script along with what it does -

what it does ...

  • sets the location & the date format to use
  • creates a set of test files from the OPs sample file names
  • gets the files from the source
  • converts the .BaseName into a [datetime] object
  • assigns the .CreationTime, .LastWriteTime, & .LastAccessTime values to the datetime from the file name
  • displays the changed values

here is the code ...

$Directory = $env:TEMP
$DateFormat = "yyyy-MM-dd"

# create some test files
$TestFileList = @(
    'FileA_2017-10-15.pdf'
    'FileB_2016-04-08.pdf'
    'FileC_2018-01-30.pdf'
    'FileD_2019-09-09_1.pdf'
    'FileE_2015-05-05_2.pdf'
    )
foreach ($TFL_Item in $TestFileList)
    {
    $Null = New-Item -Path $Directory -Name $TFL_Item -ItemType File -Force
    }

$FileList = Get-ChildItem -LiteralPath $Directory -Filter '*.pdf' -File
foreach ($FL_Item in $FileList) {

    # removed split, added regex match to work with ever-growing list of variant file names
    $Null = $FL_Item.BaseName -match '_(?<DateString>\d{4}-\d{2}-\d{2})'
    $DateString = $Matches.DateString
    $date_from_file = [datetime]::ParseExact($DateString, $DateFormat, $Null)

    $FL_Item.CreationTime = $date_from_file
    $FL_Item.LastWriteTime = $date_from_file
    $FL_Item.LastAccessTime = $date_from_file

    # show the resulting datetime info
    '=' * 20
    $CurrentFileInfo = Get-Item -LiteralPath $FL_Item.FullName
    $CurrentFileInfo.FullName
    $CurrentFileInfo.CreationTime
    $CurrentFileInfo.LastWriteTime
    $CurrentFileInfo.LastAccessTime
    }

screen output ...

====================
C:\Temp\FileA_2017-10-15.pdf

2017 October 15, Sunday 12:00:00 AM
2017 October 15, Sunday 12:00:00 AM
2017 October 15, Sunday 12:00:00 AM
====================
C:\Temp\FileB_2016-04-08.pdf
2016 April 08, Friday 12:00:00 AM
2016 April 08, Friday 12:00:00 AM
2016 April 08, Friday 12:00:00 AM
====================
C:\Temp\FileC_2018-01-30.pdf
2018 January 30, Tuesday 12:00:00 AM
2018 January 30, Tuesday 12:00:00 AM
2018 January 30, Tuesday 12:00:00 AM
====================
C:\Temp\FileD_2019-09-09_1.pdf
2019 September 09, Monday 12:00:00 AM
2019 September 09, Monday 12:00:00 AM
2019 September 09, Monday 12:00:00 AM
====================
C:\Temp\FileE_2015-05-05_2.pdf
2015 May 05, Tuesday 12:00:00 AM
2015 May 05, Tuesday 12:00:00 AM
2015 May 05, Tuesday 12:00:00 AM

i checked the files directly in explorer & they match the displayed values.

Upvotes: 1

user6811411
user6811411

Reputation:

You are quite near, you need

  • split the date part from filename and convert it to a [datetime]
  • I use a RegEx with a capture group anchored at the end $ of the BaseName
## Q:\Test\2019\05\19\SO_56211626.ps1
$Directory = "C:\TestFolder"

foreach ($file in (Get-ChildItem -Path $Directory -Filter *.pdf)){
    if($File.BaseName -match '_(\d{4}-\d{2}-\d{2})(_\d)?$'){
        $date_from_file= (Get-Date $Matches[1])

        $file.CreationTime   = $date_from_file
        $file.LastAccessTime = $date_from_file
        $file.LastWriteTime  = $date_from_file
        $file | Select-Object Name,CreationTime,LastAccessTime,LastWriteTime
    }
}

Sample output:

> Q:\Test\2019\05\19\SO_56211626.ps1

Name                 CreationTime        LastAccessTime      LastWriteTime
----                 ------------        --------------      -------------
FileA_2017-10-15.pdf 2017-10-15 00:00:00 2017-10-15 00:00:00 2017-10-15 00:00:00
FileB_2016-04-08.pdf 2016-04-08 00:00:00 2016-04-08 00:00:00 2016-04-08 00:00:00
FileC_2018-01-30.pdf 2018-01-30 00:00:00 2018-01-30 00:00:00 2018-01-30 00:00:00

An English locale (en-US) produces:

Name                 CreationTime           LastAccessTime         LastWriteTime
----                 ------------           --------------         -------------
FileA_2017-10-15.pdf 10/15/2017 12:00:00 AM 10/15/2017 12:00:00 AM 10/15/2017 12:00:00 AM
FileB_2016-04-08.pdf 4/8/2016 12:00:00 AM   4/8/2016 12:00:00 AM   4/8/2016 12:00:00 AM
FileC_2018-01-30.pdf 1/30/2018 12:00:00 AM  1/30/2018 12:00:00 AM  1/30/2018 12:00:00 AM

Upvotes: 2

Related Questions