Home > database >  Rename files in subfolders
Rename files in subfolders

Time:01-16

I am trying to rename files in subfolders in a certain pattern, but I am stuck.

The situation is as follows: I have multiple folders which are sometimes named as the target filename depending on the length, but the name does not really matter.

In each folder are always 2 files: the Target-File with a random name and the correct extension, and the Source-File which is always the correct BaseName with a txt-extension.

For example:

Folder1\7393028473.docx
Folder1\January.txt
Folder2\9373930843.pdf
Folder2\February.txt

My goal is to rename every not-txt-file with the Basename of the txt-file. Executed, it should be like:

Folder1\January.docx
Folder1\January.txt
Folder2\February.pdf
Folder2\February.txt

With gci I was able to create both lists but didn't find a good way for the renaming.

$SourceName = gci -File -Recurse | Where {$_.Extension -ne ".txt"}
$TargetName = gci -File -Recurse | Where {$_.Extension -eq ".txt"}

I did also try to use gci for renaming, but was not able to tell it to use the newname based on the txt-file:

gci -File -Recurse | Where {$_.Extension -ne ".txt"} | Rename-Item -NewName {$_.extension -eq ".txt"}

This only renamed the .docx-file to "FALSE" because the filename already exists.

What I did not try (but would be ok) is to not only rename the file, but also move it to the parent directory.

CodePudding user response:

This is one way to do it but it would fail as soon as there are 2 or more files with a different extension than .txt but having the same extension. It would also fail as soon as one folder has more than one .txt file.

# Get all folders under 'TargetDirectory'
Get-ChildItem TargetDirectory -Directory -Recurse | ForEach-Object {
    # For each sub-folder, get their files
    $childs = $_.EnumerateFiles()
    # Filter and split the child files by their extension
    $txt, $notTxt = $childs.Where({ $_.Extension -eq '.txt' }, 'Split')
    # Use the BaseName of the '.txt' File but the Extension of
    # the file being renamed
    $notTxt | Rename-Item -NewName { $txt.BaseName   $_.Extension }
}

CodePudding user response:

You can use a loop to iterate through each folder and rename the files accordingly. Here is an example of how you can achieve this using PowerShell:

$folders = gci -Directory -Recurse
foreach ($folder in $folders) {
    $targetFile = gci $folder | Where {$_.Extension -ne ".txt"}
    $sourceFile = gci $folder | Where {$_.Extension -eq ".txt"}
    $newName = $sourceFile.BaseName   $targetFile.Extension
    Rename-Item $targetFile.FullName $newName
}

This script first gets all the subfolders using gci -Directory -Recurse, then for each folder, it gets the target and source files using the Where method, constructs the new name for the target file using the base name of the source file and the extension of the target file, and finally renames the target file using the Rename-Item cmdlet.

Note, this script assumes that there is only one target file and one source file in each folder.

  • Related