Sick of sequentially named video filenames? This Powershell script will rename all 5 digit video filenames to their original date and time of creation to allow for easy sorting and cataloging.
Introduction
HD video files stored on camcorders are usually named using a 5 digit sequential filename followed by the video file extension such as MTS. The sequential filenames give no clue as to the video's content or when it was created thus making it difficult to sort and catalog the files once copied to the main computer for processing. This Powershell script will rename the files according to their original date and time of creation.
Background
My camcorder's hard drive developed a problem whereby I could not download the files to my computer. The camera's application software would simply hang on a particular file and stay frozen until I disconnected the camera and forced the app closed. This meant I could not download and then clear the hard drive ready for the next shoot. The only way to get the files off the hard drive was to manually copy the files across to my computer using Windows File Explorer.
The problem with this method is that the files are named in a sequential fashion starting at 00000.mts and incrementing by one for each subsequent video file. Using the camera's application software, the files would be copied over to the PC and renamed based on the file's original creation date and time, e.g., 20190223113432.m2ts, i.e., YYYYMMDDHHMMSS.ext format.
I needed a way to do this myself without the app and I had 1600 files to rename and thus I developed this Powershell script to do the work for me.
Using the Code
The script should be saved to a folder on the PC, e.g., D:\Scripts or C:\Utils. Someplace where you keep all your utility programs, etc.
The script can be executed from the Windows Cmd line using this syntax:
powershell ./script_path/ConvertVideoFilename.ps1 'Video_Files_Path' options
where:
script_path
is the full path to the location of this script, and Video_Files_Path
is the full path to the location where the video files are located options
are:
q
= quietmode, no messages, and e
= show error messages if in quiet mode
If no options are specified, then each file found is listed. Both options can be specified together like "qe
" or "eq
". The order is not important. Note the lack of a space between the options if both are specified.
Be sure to include any punctuation as shown above or the command will not work.
Here is the script:
$ToolPath = "F:\Downloads\Utils\exiftool-12.23\"
# Let's go!
# Check if exiftool.exe exists in the path specified
if (!(Test-Path -Path $ToolPath\exiftool.exe)){
Write-Host "The path $($ToolPath) does not contain the tool exiftool.exe."
Write-Host "Download the exiftool from https://exiftool.org/"
Write-Host "follow the instructions and save exiftool.exe"
Write-Host "somewhere on your computer, then change the toolpath"
Write-Host "in this script to the correct location and try again."
Exit
}
$Exe = $ToolPath + "exiftool.exe"
# Check if any parameters were specified. Need one parameter which
# is the path to the folder containing the video files
if ($args.Count -lt 1){
Write-Host "Missing parameter: The path to the video files has not been specified."
Exit
}
# Check the specified video files path exists
if (!(Test-Path -Path $args[0])){
Write-Host "Invalid video files path specified. Path $($args[0]) not found."
Exit
}
$VideoFilesPath = $args[0]
# Check for 2nd parameter. If specified and it's a "q",
# then enter quiet mode where no messages are shown
$QuietMode = $false
$ShowErrors = $true
if ($args[1] -ne $null){
if ($args[1] -like "*q*"){
$QuietMode = $true
$ShowErrors = $false
}
if ($args[1] -like "*e*"){
$ShowErrors = $true
}
}
$Verbose = !($QuietMode)
# Get a list of files for the specified path
$Files = Get-ChildItem -Path $VideoFilesPath
# Loop through list and process each file
$FileCount = 0
$MissingTimeCount = 0
$RenamedCount = 0
$InvalidFilenameCount = 0
$ExistsCount = 0
foreach ($File in $Files){
$FileCount += 1
# Since the filename SHOULD be a valid sequential filename
# consisting of 5 digits, split the full filename by the "."
# to obtain just the digits and the extension
$Name = $File.Name.Split("{.}")
# If the filename is indeed 5 chars long, perform the rename
if ($Name[0].Length -eq 5 -and $Name[0] -match "^\d+$"){
# Extract the original date/time stamp from the video
$Orig = &$Exe "$($VideoFilesPath)\$($File.Name)" |
Select-String -Pattern "Date/Time Original"
# Check if a timestamp was found. If not, then use the previous file's timestamp
# and increment the seconds by 1 as a best guess.
# If greater than 60, then increment minutes and so on...
if ($Orig -eq $Null){
$MissingTimeCount += 1
if ($Verbose -or $ShowErrors){
Write-host "$($File.Name) has no original timestamp, using previous + 1s"
}
$HH = [int]::Parse($PrevTimeHH) # Convert strings to integers for math
$MM = [int]::Parse($PrevTimeMM)
$SS = [int]::Parse($PrevTimeSS)
$SS += 1 # Increment seconds
if ($SS -gt 59){ # Check if over 59 etc
$SS = 0
$MM += 1
}
if ($MM -gt 59){
$MM = 0
$HH += 1
}
if ($HH -gt 23){
$HH = 0
}
$PrevTimeHH = "{0:D2}" -f $HH # Convert numbers back to 2 char string, e.g. 1 => 01
$PrevTimeMM = "{0:D2}" -f $MM
$PrevTimeSS = "{0:D2}" -f $SS
$OrigTimeShort = $PrevTimeHH + $PrevTimeMM + $PrevTimeSS
$OrigDateShort = $PrevOrigDateShort
}
else{ # If the timestamp was found
# then process the video file and use its original date/time
# Extract the date and remove the ":" chars
$OrigDate = $Orig.ToString().Substring(34,10)
$OrigDateShort = $OrigDate.Substring(0,4) + `
$OrigDate.Substring(5,2) + $OrigDate.Substring(8,2)
# Extract the time and remove the ": chars
$OrigTime = $Orig.ToString().Substring(45,8)
$OrigTimeHH = $OrigTime.Substring(0,2)
$OrigTimeMM = $OrigTime.Substring(3,2)
$OrigTimeSS = $OrigTime.Substring(6,2)
$OrigTimeShort = $OrigTimeHH + $OrigTimeMM + $OrigTimeSS
$PrevOrigDateShort = $OrigDateShort
$PrevTimeHH = $OrigTimeHH
$PrevTimeMM = $OrigTimeMM
$PrevTimeSS = $OrigTimeSS
}
$NewName = $OrigDateShort + $OrigTimeShort + "." + $Name[1]
if (Test-Path -Path $VideoFilesPath\$NewName){
$ExistsCount += 1
if ($Verbose -or $ShowErrors){
Write-Host "$($NewName) already exists. Skipped"
}
} else {
Rename-Item "$($VideoFilesPath)\$($File.Name)" $NewName
$RenamedCount += 1
if ($Verbose -or $ShowErrors){
Write-Host "$($File.Name) renamed to $($NewName)"
}
}
} else {
$InvalidFilenameCount += 1
if ($Verbose -or $ShowErrors){
Write-host "$($File.Name) skipped, filename not valid 5 digit sequential filename"
}
}
}
Write-Host "Stats:"
Write-Host "$($FileCount) Files processed"
Write-Host "$($MissingTimeCount) Files with missing original date/time stamp"
Write-Host "$($InvalidFilenameCount) Files had an invalid filename, i.e. not 5 digits"
Write-Host "$($ExistsCount) Files already exists and were skipped"
Write-Host "$($RenamedCount) Files were renamed successfully"
Write-Host "Done."
Points of Interest
This script relies on the exiftool to do the heavy lifting. I came across this utility quite by accident and am glad I did as it saved my bacon. Check out the web page for this extremely powerful and useful program.
It took me two days to write this script with a lot of help from the internet. I don't know Powershell very well, but know it's extremely powerful. I learnt quite a bit by scouring Powershell web sites for the usage of commands and how to do things I wanted to do but had no inkling of the commandlet or syntax.
Update
I found the Powershell method of renaming the files a little slow in execution and was looking for a better way to this when I came across an internet article that also used the exiftool, but interestingly, just the tool itself to rename a whole bunch of files at once! Just what I was after. Apparently, it is much, much faster to let the tool rename all the files than to repeatedly call it to rename a single file. After digging deeper into the documentation, I learned how to do it myself. It's not as straightforward as one would think, this tool has a myriad of options allowing it to perform quite complex tasks.
The short of it is this command:
ToolPath\exiftool -r "-FileName<DateTimeOriginal"
-d "Destination\%Y%m%d_%H%M%S%%-c.%%e" -ext * "SourcePath"
where:
ToolPath
is the full path to the location of this script, Destination
is the full path to the location where the renamed files should be saved, and SourcePath
is the full path to the location of the files to be renamed.
Check the tool's extensive documentation for the full syntax and the many, many more options and possibilities available. I particularly like the example given to use the file's original timestamp to create subfolders for the year and month (and day), thereby distributing the files nicely into a folder tree by date.
On a personal note, I found the easiest way to use this tool is to add the ToolPath to Windows' default app search path and executing the exiftool command in the destination folder, thereby only having to specify the source path.
History
- 10th April, 2021: Initial version
- 16th April, 2021: Using tool on its own