Home > Net >  Renaming multiple files in directory using a specific string in each file
Renaming multiple files in directory using a specific string in each file

Time:01-11

I have a folder with multiple files and need to rename them to a string inside of the folder. The string is the date of interaction.

Currently the files are named as

AUDIT-1.log
AUDIT-2.log
AUDIT-3.log

ect..

I need to have them as

AUDIT-11-08-22-1.log
AUDIT-11-07-22-2.log
AUDIT-11-08-22-3.log

The issue I am having with the current iteration of the code, the dates of all files are collected and it attempts to rename the file with all dates

EXAMPLE:

NewName: 11-08-22 11-07-22 11-06-22 11-09-22 11-08-22 11-07-22 11-06-22 11-09-22-1.LOG
OldName: C:\TestTemp\AUDIT-2.LOG

There is only one date in each file.

The following is my current code:

$dir ="C:\TestTemp"
$files = Get-ChildItem -Path "$dir\*.log"
$RegexDate = '\d\d\/\d\d\/\d\d'

Measure-Command{

$file_map = @()
foreach ($file in $files) {
    $DateName= Get-Content $files | 
Select-String $RegexDate |
foreach-object { $_.Matches.Value } |
Select-Object
    $NewDateName= $DateName.replace('/','-')
$b = 1 
    $file_map  = @{
        OldName = $file.Fullname
        NewName = "$NewDateName-$b.LOG" -f $(Get-Content $file.Fullname | Select-Object $NewDateName.Fullname)
    }
}

$file_map | ForEach-Object { Rename-Item -Path $_.OldName -NewName $_.NewName }

}

CodePudding user response:

As pointed out in the comments by Santiago Squarzon, the immediate fix is to swap $files, for $file. For code brevity, here's a single pipeline solution you can implement to attain the same results:

Select-String -Path "$dir\*.log" -Pattern '(\d \/){2}\d ' | 
    Rename-Item -NewName { 
        $_.FileName -replace '-', "-$($_.Matches.Value.Replace('/','-'))-" 
    } -WhatIf

Again, as mentioned in the comments, the use of Select-String allows the reading of file(s) presenting the opportunity to pipe directly into Rename-Item via parameter binding through its Path property. So, using a scriptblock for the new name replacement we're essentially inserting the value found from it's pattern matched into the file name where - would have been.


The -WhatIf safety/common parameter can be removed when you've dictated those are the results you are after.

CodePudding user response:

This will rename the files using their last write time. If the files were already in that format, they will not be renamed. There is a hashtable to track the increment of the suffix for the date of the file. This way the files can be organized by date.

$dir = "C:\TestTemp"
$files = Get-ChildItem -Path "$dir\*.log"


#Hashtable to track the suffix for the files
[hashtable]$dateTracking = @{}

#Using padding to format the suffix with two digits, in case there more then 9 files
#incrase it if you have more then 99 files per day increase padding
$suffixPadding = '{0:d2}'

foreach ($file in $files) {
    #Don't rename files that were already renamed
    if ($file.Name -notmatch "AUDIT-\d{2}-\d{2}-\d{2}-\d{2}\.log") {
        $date = $file.LastWriteTime.ToString("MM-yy-dd")
        #If the date is not entered in the hashtable add it with suffix 01
        if (-not $dateTracking.ContainsKey($date)) {        
            $dateTracking.Add($date, $suffixPadding -f 1)
        }
        #Else increment suffix
        else {
            $dateTracking[$date] = $suffixPadding -f ([int]$dateTracking[$date]   1)
        }
        #Here we use the date in the name of the file and getting the suffix from the hashtable
        Write-Host "Renaming $($file.Name) to AUDIT-$date-$($dateTracking[$date]).log"
        Rename-Item -Path $file -NewName "AUDIT-$date-$($dateTracking[$date]).log"
    }
}
  • Related