我有一个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,并赞扬我使用的最有影响力的资源。
答案 0 :(得分:1)
认为这是一个有趣的问题,所以我想我会在午餐时给它一个裂缝。这就是我提出的。我试图让它尽可能易读,以便逻辑易于理解。
这些是逻辑步骤
从目录中获取不以_some编号
结尾的文件列表获取名为_come number的所有文件的列表,并找到最高的数字,例如,如果有3个名为FileA_01.txt的文件,SomeDocument_03.txt,FileB_02.txt将返回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)(..*)', "`$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”的文件夹中
我想检查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
这处理:
如果要停止自动化,请调用Unregister-Event $ SourceIdentifier