Powershell-根据文件名更改文件创建日期和修改日期

时间:2019-05-19 20:13:30

标签: 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

不幸的是,它们的扫描日期与文档的实际日期不同。因此,“创建日期”和“修改日期”属性与文件名中显示的属性不同。

我希望我可以运行一个脚本来更改“创建日期”和“修改日期”以匹配文件名。

我尝试使用其他人的脚本进行此操作,但是我对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)
    }

如果由于我已有的东西不起作用而已经写了其他东西,则可以取消上面的代码。

编辑 想知道是否还可以将其添加到脚本中,以便它也可以将文件包含在子文件夹中。如果该文件夹上的“修改日期”为今天,则可能仅以该文件夹中文件的方式编写脚本。我想在一个可能具有许多子文件夹的父文件夹上运行此文件,如果这些文件夹没有今天的“修改日期”,那么它应该跳过该文件夹中的文件。我当时在想可以加快这个过程。敞开心thought,感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

您距离很近,您需要

  • 从文件名中分割日期部分,并将其转换为[datetime]
  • 我使用RegEx,并将捕获组锚定在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
    }
}

示例输出:

> 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

英语语言环境(美国)产生:

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

答案 1 :(得分:1)

[ 编辑-由于OP在我建议的修复程序中遇到了非常奇怪的错误-我无法使用示例数据重现的错误-我已将此答案更改为完整的建议代码。 编辑2-添加了新的文件名变体和代码来处理它们。
编辑3-由于示例数据再次更改,因此从拆分更改为正则表达式匹配。 [*叹息... *] ]

您实际上并不是在创建所需的datetime对象。 $date_from_file=行除了创建红色错误消息... [咧嘴]

之外,实际上不做任何其他事情

替换此行...

$date_from_file=GetFileName::[datetime])

...此行...

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

...,并且您的$date_from_file变量将包含一个正确的[datetime]对象,该对象将在您的分配中起作用。

i可能会更改这些分配的顺序,以将$file.LastAccessTime = $date_from_file置于最后,这样,下一行就不会更改它。

,该值将在每次访问文件时更改,因此可能不值得更改。 [咧嘴]


这是完整的脚本以及它的功能-

它做什么...

  • 设置要使用的位置和日期格式
  • 从OP样本文件名创建一组测试文件
  • 从源获取文件
  • .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
    }

屏幕输出...

====================
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

我直接在资源管理器中检查了文件,并且它们与显示的值匹配。

答案 2 :(得分:0)

谢谢。我被困在没有这个线程的情况下。我最终得到了一个变体,该变体将任何文件名与正确格式的日期匹配,因此:

# 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