Search code examples
windowspowershellloopsscriptingbatch-rename

Rename multiple files in a directory by looping through a list of names in a .txt / .csv file for a partial match


I'm trying to automate renaming of many multiple files in a Windows 7 directory. I need to search a source index file (.txt or .csv which is a list of extended file names) and, where there is a partial match to the original file name, copy the first 12 characters (of the relevant string in the index file) and rename the original file accordingly (and preserving original file extension).

e.g.

(a) Files currently in the Windows directory are named as follows (hundreds of files):

  • 23456abc.doc
  • 76543cab.doc
  • 92837bca.doc

(b) Values in the .txt/.csv file as follows (hundreds of values - NOTE: these do not have file extensions):

  • BetterName1.RandomText1.23456abc.MoreRandomText1
  • BetterName2.RandomText2.76543cab.MoreRandomText2
  • BetterName3.RandomText3.92837bca.MoreRandomText3

(c) Desired Result is for the files to be auto renamed as follows:

[by searching for filename in (a) within the list of values in (b) and, where there is a match, returning the first 12 characters as the new filename whilst preserving the original file extension]

  • BetterName1.doc
  • BetterName2.doc
  • BetterName3.doc

NOTE: My preference is to use an Index file for the look-up that is in .txt format. However in need I can also use a .csv

I have never used PowerShell before and am new to Windows batch scripting. I have searched around and tried to cobble together snippets of code into a Windows batch script (also tried a PowerShell script) to achieve this but my knowledge in this area is seriously lacking so unfortunately I'm still struggling away at square one.

Any assistance would be greatly appreciated. Thank you in advance.

P.S. Here is a PowerShell script that I tried to get working but to no avail.

$fdPath = 'C:\TEST\Data'
$sourcelistFiles = Get-ChildItem -Path $FDPATH\*.txt | ForEach-Object {$_.user } FullName
$findReplaceList = Import-Csv -Path $FDPATH\AllNames.csv


$totalitems = $sourcelistFiles.count
$currentrow = 0
foreach ($sourcelistFile in $sourcelistFiles)
{
    $currentrow += 1
    Write-Progress -Activity "Processing record $currentrow of $totalitems" -Status "Progress:" -PercentComplete (($currentrow / $totalitems) * 100)

    [string] $txtSourceListFile = Get-Content $sourcelistFile | Out-String

    ForEach ($findReplaceItem in $findReplaceList)
    {
        $txtSourceListFile = $txtSourceListFile -replace "$($findReplaceitem.FindString)", "$($findReplaceitem.ReplaceString)"
    }
    
    $txtSourceListFile | Set-Content ($sourcelistFile)
 -NoNewLine
}

Solution

  • $FDPATH = 'C:\TEST\Data'
    foreach($obj in (Import-Csv -Path $FDPATH\AllNames.csv)){
      foreach($thing in $(gci -Path $FDPATH\*.txt)){
        if("123.hash.avocado" -match $thing.basename){$ret = $thing.fullname}
      }
      $stuff = $obj -split "."
      ren -Path $ret -NewName $stuff[0]
    }
    

    See if this works, it iterates through the csv then iterates through the directory to see if the directory's name is in the csv's line that is being iterated, then sets a variable to be the fullname of the file and renames it to the first name before the period.