如何按顺序重命名最近的文件?

How to rename the most recent files in order?

我有一个 powershell 脚本(由自动化软件触发)。它有效地按目录重命名文件,后跟下划线、前导零和顺序编号。

$i = 0
$folder = Any-path
Get-ChildItem -Path $folder |ForEach-Object 
{$extension = $_.Extension
$newName = $_.Directory.Name + '_{0:d3}{1}' -f  $i, $extension
$i++
Rename-Item -Path $_.FullName -NewName $newName}

问题是每次触发脚本时,它都会重命名目录中的每个文件,效率低下。

我只想重命名不符合命名方案 (FolderName_01.ext) 的文件,并按照添加的顺序重命名异常,从顶点继续。

所以

会变成

FolderName_01 到 FolderName_05 ,Anomaly2 重命名为 FolderName_04,因为它创建得较早。

我知道我可以使用

Get-ItemProperty '$filename' | select CreationTime

查看每个文件的日期,但我的大脑开始发热,因为我试图弄清楚如何使用该信息重命名文件,按创建日期,从最后一个正确命名的文件中选取。

非常感谢任何帮助!


我在这方面做了很多工作。我得到了帮助并做了很多阅读。此解决方案在某些方面可能很粗糙,但它可以完成工作并且可以 运行 在后台自动执行操作 - 有一个警告:Powershell 控制台必须保持打开状态。

我还没有想出如何使它成为永久的 WMI 事件绑定。

解法:

#REQUIRES -Version 4.0

#This is a string of folders you'd like to monitor
$Monitored = 'C:\Users\Me\Desktop\Pic Test\Tom Hiddleston', 'C:\Users\Me\Desktop\Pic Test\Kate Bosworth'

#This part is selecting the folder paths to be processed indvidually
$MatchPath = @($Monitored | Where-Object { Test-Path -Path $_ } | ForEach-Object {
$Path = $_;

$Watcher = New-Object System.IO.FileSystemWatcher -Property @{
    Path = $Path;
    Filter = '*.*';
    IncludeSubdirectories = $True;
    NotifyFilter = [System.IO.NotifyFilters]'FileName, LastWrite'}

#This may be unnecessary, but it's there to add the folder name to the -#SourceIdentifier, which makes the automation easier to shut down.
$ID = Split-Path $Path -Leaf

#Here it's important that the variable have the same name as the delete section, because it passes to the New-Object creation at the bottom.
#In this case, four events will be created. Two folders x two actions.
$FileAction = Register-ObjectEvent -InputObject $Watcher Created -SourceIdentifier FileCreated_$ID -Action {

    $Local = Split-Path ($Event.SourceEventArgs.FullPath)
    $i = 0

    #Selects which file extentions to include in renaming
    Filter Where-Extension {
    Param( [String[]] $Extension = ('.bmp', '.jpg', '.png', '.gif', '.jpeg', '.avi')) $_ |
    Where-Object { $Extension -contains $_.Extension }}

    #Orders all the files by their CreationTime
    Function Global:File-Order ($Local) {Get-ChildItem -Path $Local | 
    Where-Extension .jpg,.bmp,.png,.jpeg,.gif,.avi |
    Select-Object Name,FullName,CreationTime|Sort-Object -Property CreationTime}

    #Returns a file's extension
    Function Global:File-Ext ($File) {Get-ItemProperty $File| Select-Object -Expand Extension}

    #Returns the name the file should be - the NewName
    $NewBase = ((Split-Path $Local -Leaf) + '_{0:d2}{1}' -f  $i, $Ext).Split("\.")


    File-Order ($Local) | ForEach-Object -Begin {$i = 0} `
    -Process {
        $Ext = File-Ext ($_.FullName) 
        $NewName = $NewBase[0] + $i

        if (!(Test-Path (-Join ($Local,'\',$NewName,'.*'))))
        {Rename-Item -Path $_.FullName -NewName (-Join ($NewName,$Ext))}
        $i++ }
        };       

$FileAction = Register-ObjectEvent -InputObject $Watcher Deleted -SourceIdentifier FileDeleted_$ID -Action  {

    $Local = Split-Path ($Event.SourceEventArgs.FullPath)
    $i = 0

    #Selects which file extentions to include in renaming
    Filter Where-Extension {
    Param( [String[]] $Extension = ('.bmp', '.jpg', '.png', '.gif', '.jpeg', '.avi')) $_ |
    Where-Object { $Extension -contains $_.Extension }}

    #Orders all the files by their CreationTime
    Function Global:File-Order ($Local) {Get-ChildItem -Path $Local | 
    Where-Extension .jpg,.bmp,.png,.jpeg,.gif,.avi |
    Select-Object Name,FullName,CreationTime|Sort-Object -Property CreationTime}

    #Returns a file's extension
    Function Global:File-Ext ($File) {Get-ItemProperty $File| Select-Object -Expand Extension}

    #Returns the name the file should be - the NewName
    $NewBase = ((Split-Path $Local -Leaf) + '_{0:d2}{1}' -f  $i, $Ext).Split("\.")


    File-Order ($Local) | ForEach-Object -Begin {$i = 0} `
    -Process {
        $Ext = File-Ext ($_.FullName) 
        $NewName = $NewBase[0] + $i

        if (!(Test-Path (-Join ($Local,'\',$NewName,'.*'))))
        {Rename-Item -Path $_.FullName -NewName (-Join ($NewName,$Ext))}
        $i++ }
        }; 

New-Object PSObject -Property @{ Watcher = $Watcher; OnCreated = $FileAction };

}); 

#These will the stop the scripts
#Unregister-Event FileCreated_Pic Test -Verbose
#Unregister-Event FileDeleted_Pic Test -Verbose
#Unregister-Event FileCreated_Another Test -Verbose
#Unregister-Event FileDeleted_Another Test -Verbose

#This will stop all the scripts at once, including any others you may have running; so use Get-EventSubscriber first, to see what's running, then.
#Get-EventSubscriber | Unregister-Event -Verbose

我要感谢@justinf 并感谢我使用的最有影响力的来源。

认为这是一个有趣的问题,所以我想我会在午餐时试一试。这就是我想出的。我尽量使其具有可读性,以便逻辑易于理解。

这些是逻辑步骤

从不以_some 数字结尾的目录中获取文件列表

获取所有名为 _come number 的文件的列表并找到最大的编号,例如,如果有 3 个名为 FileA_01.txt、SomeDocument_03.txt、FileB_02.txt 的文件,它将 return 3 因为那是最高的数字。

现在给最高数字加 1,这样我们就可以用它来重命名文件

现在我们循环思考我们需要按照 LastWriteTime 的顺序重命名的文件列表并重命名它们。

这是我的测试文件文件夹最初的样子。

这是我 运行 脚本后的样子。

$filesLocation = 'c:\Dump\test'

#Step 1# Get a list of files we need to rename , any files that do not end with _number 
$FilesToRename = Get-ChildItem -Path $filesLocation | Where-Object {$_.Name -notmatch ".*_\d*"} | select-object Name,FullName,LastWriteTime

#Step 2 # Get highest file number so if the highest file name is SomeDocument_03.txt it will return 3 
$HighestNumber = (((Get-ChildItem -Path $filesLocation | Where-Object {$_.Name -match ".*_\d*"}).name -replace '(.*)(\d\d)(..*)', "`") | measure -Maximum).Maximum

#Step 3 # Get the next number that we will use , becasue measure -Maximum).Maximum returns 3 we need to add the 0 infront of the number if it is shorter than two digits 
[int]$NextNumber =  IF ($HighestNumber -lt 9) {"0"+ ($HighestNumber+1).tostring()} else {($HighestNumber+1).tostring()}

#Step 4 # Rename the files that need renaming in the order of their last write time 
foreach ($File in ($FilesToRename | Sort-Object -Property LastWriteTime) )
{
  $SplitName = ($File.Name.Split("."))

  $NewName = $SplitName[0] + '_' +$NextNumber +'.'+$SplitName[1]

  Rename-Item -LiteralPath $File.FullName -NewName $NewName

  $NextNumber = ++$NextNumber
}

这似乎可以解决问题,但我想 运行 更多测试,可以肯定的是,@justinf

我想要的是重命名文件 - 像这样:ParentFolder_000 - 并在我创建文件的日期之前保持它们的顺序。所以...在这里你可以看到我有一堆文件,随机命名,在一个名为 "Kate Bosworth"

的文件夹中

我想检查 CreationTime 属性 并重命名文件 KateBosworth_00#

我想出的脚本将按 CreationTime 重新排序文件,即使我删除或重命名其中一个文件...

所以,最后,这是我想出的脚本。

#This is a string of folders you'd like to monitor
$Monitored = 'C:\Users\Me\Desktop\Pic Test\Tom Hiddleston', 'C:\Users\Me\Desktop\Pic Test\Kate Bosworth'

#This part is selecting the folder paths to be processed indvidually
$MatchPath = @($Monitored | ? { Test-Path -Path $_ } | % {
$Path = $_;

$Watcher = New-Object System.IO.FileSystemWatcher -Property @{
    Path = $Path;
    Filter = '*.*';
    IncludeSubdirectories = $True;
    NotifyFilter = [System.IO.NotifyFilters]'FileName, LastWrite'}

#This may be unnecessary, but it's there to add the folder name to the -#SourceIdentifier, which makes the automation easier to shut down.
$ID = Split-Path $Path -Leaf

#Here it's important that the variable have the same name as the delete section, because it passes to the New-Object creation at the bottom.
#In this case, four events will be created. Two folders x two actions.
$FileAction = Register-ObjectEvent -InputObject $Watcher Created -SourceIdentifier FileCreated_$ID -Action {

    $Local = Split-Path ($Event.SourceEventArgs.FullPath)
    $i = 0

    #Selects which file extentions to include in renaming
    Filter Where-Extension {
    Param( [String[]] $Extension = ('.bmp', '.jpg', '.png', '.gif', '.jpeg', '.avi')) $_ |
    Where-Object { $Extension -contains $_.Extension }}

    #Orders all the files by their CreationTime
    Function Global:File-Order ($Local) {Get-ChildItem -Path $Local | 
    Where-Extension .jpg,.bmp,.png,.jpeg,.gif,.avi |
    Select-Object Name,FullName,CreationTime|Sort-Object -Property CreationTime}

    #Returns a file's extension
    Function Global:File-Ext ($File) {Get-ItemProperty $File| Select-Object -Expand Extension}

    #Returns the name the file should be - the NewName
    $NewBase = ((Split-Path $Local -Leaf) + '_{0:d2}{1}' -f  $i, $Ext).Split("\.")


    File-Order ($Local) | ForEach-Object -Begin {$i = 0} `
    -Process {
        $Ext = File-Ext ($_.FullName) 
        $NewName = $NewBase[0] + $i

        if (!(Test-Path (-Join ($Local,'\',$NewName,'.*'))))
        {Rename-Item -Path $_.FullName -NewName (-Join ($NewName,$Ext))}
        $i++ }
        };       

$FileAction = Register-ObjectEvent -InputObject $Watcher Deleted -SourceIdentifier FileDeleted_$ID -Action  {

    $Local = Split-Path ($Event.SourceEventArgs.FullPath)
    $i = 0

    #Selects which file extentions to include in renaming
    Filter Where-Extension {
    Param( [String[]] $Extension = ('.bmp', '.jpg', '.png', '.gif', '.jpeg', '.avi')) $_ |
    Where-Object { $Extension -contains $_.Extension }}

    #Orders all the files by their CreationTime
    Function Global:File-Order ($Local) {Get-ChildItem -Path $Local | 
    Where-Extension .jpg,.bmp,.png,.jpeg,.gif,.avi |
    Select-Object Name,FullName,CreationTime|Sort-Object -Property CreationTime}

    #Returns a file's extension
    Function Global:File-Ext ($File) {Get-ItemProperty $File| Select-Object -Expand Extension}

    #Returns the name the file should be - the NewName
    $NewBase = ((Split-Path $Local -Leaf) + '_{0:d2}{1}' -f  $i, $Ext).Split("\.")


    File-Order ($Local) | ForEach-Object -Begin {$i = 0} `
    -Process {
        $Ext = File-Ext ($_.FullName) 
        $NewName = $NewBase[0] + $i

        if (!(Test-Path (-Join ($Local,'\',$NewName,'.*'))))
        {Rename-Item -Path $_.FullName -NewName (-Join ($NewName,$Ext))}
        $i++ }
        }; 

New-Object PSObject -Property @{ Watcher = $Watcher; OnCreated = $FileAction };

}); 

#These will the stop the scripts
#Unregister-Event FileCreated_Pic Test
#Unregister-Event FileDeleted_Pic Test
#Unregister-Event FileCreated_Another Test
#Unregister-Event FileDeleted_Another Test

这处理:

  • 正在按创建时间顺序重命名文件
  • 保持文件的顺序,即使一个被删除(不处理重命名实例,但是当添加或删除某些东西时重命名的任何东西都会被修复)
  • 它 运行 与 Powershell 一起使用,因此不需要第三方软件。 (我不确定这与哪些版本兼容。)
  • 它可以观看多个目录。
  • 按扩展名过滤。 (如果您想添加一些 if 语句,可以为不同的文件扩展名添加不同的命名方案)。

如果你想停止自动化,调用Unregister-Event $SourceIdentifier