flyingduck92
flyingduck92

Reputation: 1654

How to rename multiple files in powershell from parent folder?

Hello I would like to know is there a way to replace multiple filenames from parent folder?

I was able to rename multiple files using command below, but I have to access each folder first to rename multiple files.

dir .\* -include ('*.mp4','*.srt') | Rename-Item -NewName { $_.Name -replace '\[','' -replace '\]','' } 

I was trying to replace dir .\* to dir .\**\* to select from parent folder but didn't work.

What am I missing?

Upvotes: 2

Views: 1113

Answers (4)

flyingduck92
flyingduck92

Reputation: 1654

I just found out I could use dir . to select all files (with specific file types), including files in subdirectories.

dir . -Recurse -Include ('*.srt', '*.mp4') | Rename-Item -NewName { $_.Name -replace '\[|\]','' }

Upvotes: 1

Theo
Theo

Reputation: 61263

You can do that by adding the -Recurse switch to Get-ChildItem (dir is alias to Get-ChildItem).
When searching for files that contain square brackets, you need to use the -LiteralPath parameter.

Also, be aware that there is a snag if you pipe the results from that directly to Rename-Item..
When doing so, Get-ChildItem may pick up the already processed files again, wasting time of course, so to prevent that you can either do:

$rootFolder = 'X:\WhereTheFilesAre'
(Get-ChildItem -LiteralPath $rootFolder -Include '*.mp4','*.srt' -File -Recurse) | 
    Rename-Item -NewName { $_.Name -replace '\[|]' } 

or

$rootFolder = 'X:\WhereTheFilesAre'
$files = Get-ChildItem -LiteralPath $rootFolder -Include '*.mp4','*.srt' -File -Recurse
foreach ($file in $files) { 
    $file | Rename-Item -NewName { $file.Name -replace '\[|]' } 
}

Upvotes: 5

Steven
Steven

Reputation: 7087

In additional to marsze's concise answer and realizing this isn't really a performance question:

-Include is much slower than -Filter because it filters after retrieving from the file system. Whereas, -Filter has the file system do the heavy lifting. In essence -Filter is a nuanced version of moving filtering operations left in the command/pipeline to improve performance. However, -Filter doesn't take multiple values! That said, you may still be able to exploit this characteristic using a loop, something like:

'*.mp4','*.srt' |
ForEach-Object{
    Get-ChildItem .\ -Filter $_ -File
} | 
Rename-Item -NewName { $_.Name -replace '\[|\]' } 

-File works even though you are using -Recurse and may carry a modest performance improvement. I also shortened the -replace to 1 operation which can only help further.

Upvotes: 4

marsze
marsze

Reputation: 17164

What you probably want is the -Recurse switch:

dir "the folder" -Recurse -Include ('*.mp4','*.srt')

Note that this will recurse all levels of subdirectories.

Upvotes: 3

Related Questions