Powershell-更改基于文件名创建和修改的文件日期

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-

我有很多文件扫描的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-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