【问题标题】:Extract dates from filenames then process files by date in ascending order - Powershell从文件名中提取日期,然后按日期升序处理文件 - Powershell
【发布时间】:2020-01-23 02:59:58
【问题描述】:

首先,我将提供我的代码,然后进行解释。

$toImport = gci "\\server\folder\*" -include "Examplefile*.txt"
$toImport = $toImport.fullname

$date_of_file = @()

foreach($item in $toImport){
    $date_of_file += (split-path $item -leaf).substring(11,6) 

}

write-host ($date_of_file | sort-object)

我使用 get-childitem 获取文件名,然后将它们的完整路径放入数组中。我的 $toImport 变量包含文件路径,它看起来像:

\\server\folder\Examplefile010220.txt
\\server\folder\Examplefile010320.txt
\\server\folder\Examplefile010420.txt
\\server\folder\Examplefile010520.txt
\\server\folder\Examplefile120919.txt

然后我使用split-path 来获取文件名,我可以在其中运行.substring() 以提取日期,然后我将这些日期添加到变量$date_of_file 中,使用上面的示例将保存这些值...010220 010320 010420 010520 120919

然后我尝试按升序对这些日期进行排序,因为我的脚本的后面部分将处理这些文件,但它们必须按顺序完成。

我尝试修复上面发布的脚本的一些事情: (get-date -date $date_of_file | sort-object)

($date_of_file.ToString('MMddyy') | sort-object)

$date_of_file += ((split-path $item -leaf).substring(11,6) ).toString("MMddyy")

$date_of_file += get-date -date ((split-path $item -leaf).substring(11,6) )

($date_of_file | Sort-Object { $_. -as [datetime] })

$date_of_file += [datetime]::parseexact(((split-path $item -leaf).substring(11,6) ), 'MMddyy', $null).ToString('MMddyy')

我怎样才能让它按日期升序排序?到目前为止,每次我尝试某些事情时都会遇到错误,或者这个日期仍然在列表的末尾,“120919”,它应该是第一个。

=================更新

$toImport = gci "\\server\folder\*" -include "Examplefile*.txt"
$toImport = $toImport.fullname
cls

$date_of_file = @()

foreach($item in $toImport){
    $date_of_file += [datetime]::parseexact(((split-path $item -leaf).substring(11,6) ), 'MMddyy', $null)

}

write-host ($date_of_file | Sort-Object)

这一位似乎有效,但它将日期格式转换为类似于Thursday, January 2, 2020 12:00:00 AM 的格式。我尝试对结果执行 .ToString('MMddyy') 但我收到此错误Cannot find an overload for "ToString" and the argument count: "1".

【问题讨论】:

  • 那行不通。你可以看到我在上面尝试过。在对日期执行 parseexact 函数后,我确实得到了日期......但是使用($date_of_file | Sort-Object) 对其进行排序时无法正常工作这是我问题的基础。
  • 这是它的排序顺序,让我抓狂:010220 010320 010420 010520 120919

标签: powershell


【解决方案1】:

一种简洁高效的解决方案,直接按照文件名中嵌入的MMddyy 格式的日期字符串所暗示的时间顺序对Get-ChildItem 输出的System.IO.FileInfo 实例进行排序:

Get-ChildItem \\server\folder -Filter Examplefile*.txt |
  Sort-Object { $_.BaseName -replace '.+(\d{2})(\d{2})(\d{2})', '$3$1$2' }
  • Get-ChildItem \\server\folder -Filter Examplefile*.txt:

    • -Filter 是查找与给定通配符模式匹配的文件的最有效方法,因为它在源(文件系统)进行过滤,而不是先检索所有项目,然后在事后进行 PowerShell 过滤(-Include 会发生这种情况)。
  • Sort-Object { $_.BaseName -replace '.+(\d{2})(\d{2})(\d{2})', '$3$1$2' }:

    • 将脚本块 ({ ... }) 传递给 Sort-Object 的(隐含)-Property 参数会导致为每个输入对象评估脚本块,手头的输入对象反映在自动变量中$_.

    • 1234563排序等于时序排序。

【讨论】:

  • 谢谢,我已经放弃了我的 .substring() ,转而采用这种方式。看起来灵活了很多。我很感激。
【解决方案2】:

这可能对你有用。它添加了一个 SortableName 属性,即 yyddMM,然后按该属性排序:

dir "\\server\folder\*" -include "Examplefile*.txt" | `
  Select-Object -Property *, @{ Name = 'SortableName'; Expression = {$_.BaseName.Substring(15) + $_.BaseName.Substring(11,4) }} | `
  Sort-Object -Property SortableName | Select-Object -Property FullName

【讨论】:

  • 请注意,您不需要为了排序而创建中间计算属性;您可以将您的脚本块 ({$_.BaseName....}) 直接 传递给 Sort-Object -Property
【解决方案3】:

我认为您看到的内容可能有问题。您的排序列表应该在“最新优先”列表的末尾有 120919 文件,因为其他列表都在 2020 年,而不是 2019 年。

但是,这是我解决问题的版本。在这种情况下,“魔术”只是从文件的.BaseName 末尾获取数字。既然你把它扔掉了,我不得不使用拆分和正则表达式。 [咧嘴一笑]

$FileNameList = @(
    '\\server\folder\Examplefile010220.txt'
    '\\server\folder\Examplefile010320.txt'
    '\\server\folder\Examplefile010420.txt'
    '\\server\folder\Examplefile010520.txt'
    '\\server\folder\Examplefile120919.txt'
    )

$FileNameList |
    # this would be far easier if you have left things as fileinfo objects [*grin*] 
    Sort-Object -Descending -Property {
        [datetime]::ParseExact(($_.Split('.')[0] -replace '.+(\d{6})', '$1'), 'MMddyy', $Null)
        }

输出...

\\server\folder\Examplefile010520.txt
\\server\folder\Examplefile010420.txt
\\server\folder\Examplefile010320.txt
\\server\folder\Examplefile010220.txt
\\server\folder\Examplefile120919.txt

注意最后一个文件是2019年的,其他都是2020年的。[grin]

【讨论】:

    【解决方案4】:

    接受的答案似乎是一个很好的解决方案。这是我更新后的答案,为您提供了一个已排序的 [pscustomobjects] 数组,其中包含文件名,然后您可以使用 $date_of_file.fileNM 引用回您的文件名

    $toImport = gci "server\folder\*"
    $toImport = $toImport.fullname
    
    $date_of_file = @()
    
    foreach($item in $toImport){
        $date_of_file += [pscustomobject]@{
                          "fileNM" = $item;
                          "dispDate" = (split-path $item -leaf).substring(11,6);
                          "dateStamp"=  [datetime]::parseexact((split-path $item -leaf).substring(11,6),'MMddyy', $null)
                          }
        }
    
    $date_of_file = $date_of_file | Sort-Object -Property dateStamp
    
    $date_of_file.dispDate
    

    -----------下面的旧答案-----------

    这对我有用:

    $date_of_file = @()
    
    
    $date_of_file +=  [datetime]::parseexact("010220", 'MMddyy', $null)
    $date_of_file +=  [datetime]::parseexact("010320", 'MMddyy', $null)
    $date_of_file +=  [datetime]::parseexact("010420", 'MMddyy', $null)
    $date_of_file +=  [datetime]::parseexact("010520", 'MMddyy', $null)
    $date_of_file +=  [datetime]::parseexact("120919", 'MMddyy', $null)
    
    
    $date_of_file | Sort-Object {$_ -as [datetime]}
    

    【讨论】:

    • 看起来很简单,但这样做不会将其格式化为 MMddyy。它的格式类似于Monday, December 9, 2019 12:00:00 AM
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多