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

时间:2015-05-07 19:24:41

标签: powershell-v3.0

我有一个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_02
  • FolderName_03
  • Anomaly1-最新
  • Anomaly2-早到

会变成

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,并赞扬我使用的最有影响力的资源。

2 个答案:

答案 0 :(得分:1)

认为这是一个有趣的问题,所以我想我会在午餐时给它一个裂缝。这就是我提出的。我试图让它尽可能易读,以便逻辑易于理解。

这些是逻辑步骤

从目录中获取不以_some编号

结尾的文件列表

获取名为_come number的所有文件的列表,并找到最高的数字,例如,如果有3个名为FileA_01.txt的文件,SomeDocument_03.txt,FileB_02.txt将返回3,因为这是最高的数字。

现在将1添加到最高编号,以便我们可以使用它来重命名文件

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

这是我的测试文件文件夹开始看起来像。

enter image description here

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

enter image description here

$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)(..*)', "`$2") | 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
}

答案 1 :(得分:1)

这似乎解决了这个问题,但我想要运行更多的测试,确定,@ justinf

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

here you can see I have a bunch of files, randomly named, and inside a folder named "Kate Bosworth"

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

enter image description here

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

enter image description here

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

#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

这处理:

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

如果要停止自动化,请调用Unregister-Event $ SourceIdentifier