Powershell-更改基于文件名创建和修改的文件日期
我有很多文件扫描的PDF文件,文件名带有包含日期。例如:Powershell-更改基于文件名创建和修改的文件日期,powershell,Powershell,我有很多文件扫描的PDF文件,文件名带有包含日期。例如: FileA_2017-10-15.pdf FileB_2016-04-08.pdf FileC_2018-01-30.pdf 有些文件的结尾还带有下划线,例如 FileD_2018-01-30_1.pdf FileE_2018-01-30_2.pdf FileF_Example_2018-01-30_1.pdf FileG_Example_2018-01-30_2.pdf 甚至有一些在日期前有两个下划线,例如 FileD_2018-
FileA_2017-10-15.pdf
FileB_2016-04-08.pdf
FileC_2018-01-30.pdf
有些文件的结尾还带有下划线,例如
FileD_2018-01-30_1.pdf
FileE_2018-01-30_2.pdf
FileF_Example_2018-01-30_1.pdf
FileG_Example_2018-01-30_2.pdf
甚至有一些在日期前有两个下划线,例如
FileD_2018-01-30_1.pdf
FileE_2018-01-30_2.pdf
FileF_Example_2018-01-30_1.pdf
FileG_Example_2018-01-30_2.pdf
不幸的是,扫描它们的日期与文档的实际日期不同。因此,“创建日期”和“修改日期”属性与文件名中显示的属性不同
我想要一个脚本,我可以运行更改“日期创建”和“日期修改”匹配的文件名
我尝试使用其他人的脚本进行此操作,但我对PowerShell了解不够,无法使其真正工作。请注意,我不想更改文件名,只想更改时间戳
$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)
}
如果由于我的代码不起作用而已经编写了其他代码,则可以删除上面的代码
编辑
想知道是否也可以添加到脚本中,以便它也可以包含子文件夹中的文件。也许它可以脚本化的方式,只考虑文件夹中的文件,如果在文件夹上修改的日期是今天。我想在可能有许多子文件夹的父文件夹上运行此操作,如果这些文件夹的“修改日期”不是今天,那么它应该跳过该文件夹中的文件。我在想这可以加快进程。敞开心扉,感谢你的帮助 你离得很近,你需要
- 从文件名中拆分日期部分并将其转换为[datetime]
- 我使用带有捕获组的正则表达式,捕获组锚定在BaseName的
末尾$
> 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
英语区域设置(en-US)产生:
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
你离得很近,你需要
- 从文件名中拆分日期部分并将其转换为[datetime]
- 我使用带有捕获组的正则表达式,捕获组锚定在BaseName的
末尾$
> 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
英语区域设置(en-US)产生:
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
[
编辑-由于OP在我建议的修复中出现了非常奇怪的错误-我无法用示例数据重现这些错误-我已将此答案更改为完整的建议代码。
编辑2-添加新的文件名变体和代码以处理它们。编辑3-从拆分更改为正则表达式匹配,因为示例数据再次更改。[*叹气…*] ] 实际上,您并没有创建所需的datetime对象。
$date\u from\u file=
行实际上除了创建红色错误msgs之外,没有做任何事情。。。[咧嘴笑]
替换此行
$date_from_file=GetFileName::[datetime])
。。。用这句话
$date_from_file = [datetime]::ParseExact($File.BaseName.Split('_')[-1], $DateFormat, $Null)
。。。您的$date\u from_file
变量将包含一个适当的[datetime]
对象,该对象将在您的作业中工作
我可能会更改这些赋值的顺序,将$file.LastAccessTime=$date\u from\u file
放在最后,这样它就不会被下一行更改
此外,该值将在访问文件时随时更改,因此可能不值得更改。[咧嘴笑]
以下是完整的脚本以及它的作用- 它的作用
- 设置要使用的位置和日期格式
- 根据OPs示例文件名创建一组测试文件
- 从源获取文件
- 将
转换为.BaseName
对象[datetime]
- 将
,.CreationTime
,&.LastWriteTime
值从文件名分配给日期时间.LastAccessTime
- 显示更改的值
$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
}
我直接在资源管理器中检查了这些文件&它们与显示的值匹配 [
编辑-由于OP在我建议的修复中出现了非常奇怪的错误-我无法用示例数据重现这些错误-我已将此答案更改为完整的建议代码。
编辑2-添加新的文件名变体和代码以处理它们。编辑3-从拆分更改为正则表达式匹配,因为示例数据再次更改。[*叹气…*] ] 实际上,您并没有创建所需的datetime对象。
$date\u from\u file=
行实际上除了创建红色错误msgs之外,没有做任何事情。。。[咧嘴笑]
替换此行
$date_from_file=GetFileName::[datetime])
。。。用这句话
$date_from_file = [datetime]::ParseExact($File.BaseName.Split('_')[-1], $DateFormat, $Null)
。。。您的$date\u from_file
变量将包含一个适当的[datetime]
对象,该对象将在您的作业中工作
我可能会更改这些赋值的顺序,将$file.LastAccessTime=$date\u from\u file
放在最后,这样它就不会被下一行更改
此外,该值将在访问文件时随时更改,因此可能不值得更改。[咧嘴笑]
以下是完整的脚本以及它的作用- 它的作用
- 设置要使用的位置和日期格式
- 根据OPs示例文件名创建一组测试文件
- 从源获取文件
- 将
转换为.BaseName
对象[datetime]
- 将
,.CreationTime
,&.LastWriteTime
值从文件名分配给日期时间.LastAccessTime
- 显示更改的值
$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
}
我直接在资源管理器中检查了这些文件&它们与显示的值匹配 谢谢。我没有这根线就卡住了。我最终得到了一个变体,它将任何文件名与格式正确的日期相匹配,因此:
# 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
#像这样呼叫:
#powershell-NoLogo-ExecutionPolicy Unrestricted-Sta-NonInteractive-WindowStyle Normal-File.“\Rename\u files\u selected\u folders\u ModifyDateStamps.ps1”-文件夹“T:\files”
# 1. 将命令行参数1捕获为m