【问题标题】:Powershell - change file Date Created and Date Modified based on FilenamePowershell - 根据文件名更改文件创建日期和修改日期
【发布时间】:2020-02-23 07:20:03
【问题描述】:

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

如果已经写了别的东西,上面的代码可以被刮掉,因为我没有工作。

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

【问题讨论】:

    标签: powershell


    【解决方案1】:

    你很近,你需要

    • 从文件名中拆分日期部分并将其转换为 [日期时间]
    • 我使用正则表达式,捕获组锚定在 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
    

    英语语言环境(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
    

    【讨论】:

    • 嗯。我使用 Powershell ISE 运行了您的脚本,但什么也没发生。文件日期没有改变,也没有输出。也许我错过了什么?
    • 好的,所以它只有在文件名是“FileA_yyyy-mm-dd”时才有效。这只是一个例子,那么我们如何使它匹配任何文件名,后跟下划线和日期?
    • 但这 IS 正是 RegEx 所做的,如果按原样复制,它也可以在 ISE 中使用。`
    • 我不确定我是否完全理解。所以也许 PowerShell 不是最好的工具。对不起我的无知。另外,我刚刚发现有时我的文件末尾也可能有下划线。例如,它可能是 ExampleFile_10-15-2017_2。
    • 如果您在不告诉我们的情况下更改了您的要求,则解决方案将不适合。我的 RegEx 需要您的示例的格式,下划线 4digits dash 2digits dash 2digits 在 BaseName 的末尾。如果 RegEx 不匹配,则忽略该文件。 Lee_Dailey 的 ParseExact 错误,因为模式不匹配。所以我建议在一个新问题中提供更多真实世界的例子——这个问题已经正确回答了你最初的要求。浪费别人的时间不会让你成为朋友。
    【解决方案2】:

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

    您实际上并没有创建所需的日期时间对象。 $date_from_file= 行实际上除了创建红色错误消息之外没有做任何事情... [grin]

    替换这一行...

    $date_from_file=GetFileName::[datetime])
    

    ...用这一行...

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

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

    我可能会更改这些分配的顺序以将$file.LastAccessTime = $date_from_file LAST 放在最后,这样它就不会被下一行更改。

    此外,该值会在文件被访问时随时更改,因此可能不值得更改。 [咧嘴一笑]


    这里是完整的脚本以及它的作用 -

    它的作用......

    • 设置要使用的位置和日期格式
    • 根据 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
    

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

    【讨论】:

    • 我听从了您的建议并遇到了以下错误:使用“3”参数调用“ParseExact”的异常:“字符串未被识别为有效的日期时间。”在 line:6 char:5 + $date_from_file = [datetime]::ParseExact($File.BaseName.Split('_' ... + ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [] , MethodInvocationException + FullyQualifiedErrorId : FormatException 异常设置 "CreationTime": "Cannot convert null to type "System.DateTime"." At line:8 char:5 + $file.CreationTime = $date_from_file
    • @JadonR - 文件的确切名称是什么?我用您发布的那些进行了测试,并且按预期工作。
    • @LotPings - 我应该用完整代码替换“用那个替换这个”吗?
    • 这就是@Lee_Dailey 的建议,我刚刚从您的代码中替换了该行。
    • 我正在使用的文件的确切名称是“FileA_2016-10-07.pdf”。只要这是目录中唯一的文件,我得到的错误就是:使用“3”参数调用“ParseExact”的异常:“字符串未被识别为有效的日期时间。”
    【解决方案3】:

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

    # 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 
    

    【讨论】:

      猜你喜欢
      • 2022-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-10
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多