Adamantium23
Adamantium23

Reputation: 51

Add leading zero to file names using PowerShell

I have a folder that contains multiple hunderd .mp3-files, all with the same name and an ascending number. The filenames look like this:

Test 01.mp3
Test 02.mp3
Test 03.mp3
Test 100.mp3
Test 101.mp3
Test 102.mp3

As you can see, the number of leading zeros in the first files is wrong, as they should have one more. I'd like to use PowerShell to solve the problem as I am currently learning to operate this quite helpful tool.

I tried to count the digits in the file names using the Replace Operator to filter out any non-digit characters. I assumed that the first 99 files would have three digits while the other files would have more (counting the '3' of the .mp3 file extension)

Get-Childitem | Where {($_.Name.Replace("\D","")).Length -le 3}

That should give me any files that have 3 or less digits in their file name - but it doesnt. In fact, it shows none. If i increase the number at he end to 11, i get the first three test files, increasing it to 12 shows all six of them. I assume that the Replace-Operator doesn't get applied to the file name before the filtering based on the Length-Operator, although I used brackets around $_.Name.Replace("\D","")

What the hell am I doing wrong?

Upvotes: 2

Views: 933

Answers (3)

Random Tourist
Random Tourist

Reputation: 191

If you know how long the number should be represented, you can use ToString to transform an int into an n digits-long string (with potential leading 0s). For instance to have a 3 digits-long number you can use .ToString('000').

So for the question:

Get-ChildItem | ForEach-Object { $_.BaseName -match '\d+' | Out-Null; $digits = $Matches[0]; Rename-Item $_ ($_.Name -replace $digits, ([int]$digits).ToString('000')) }

(The Out-Null is to prevent the -match output to be displayed.)

Upvotes: 0

Theo
Theo

Reputation: 61093

By replacing "Test " with "Test 0", you would still not achieve what you want on files that are numbered Test 1.mp3 (as this will become Test 01.mp3, which is one leading zero short).

You can make sure all files will have a 3-digit sequence number by doing this:

Get-Childitem -Path 'D:\Test' -Filter '*.mp3' -File | 
    Where-Object {$_.BaseName -match '(\D+)(\d+)$'} | 
    Rename-Item -NewName { '{0}{1:D3}{2}' -f $Matches[1], [int]$Matches[2], $_.Extension }

With this, also wrongly named files like Test 00000003.mp3 wil be renamed as Test 003.mp3

Upvotes: 1

Adamantium23
Adamantium23

Reputation: 51

I figures it out: Get-ChildItem | Where {($_.Name -replace "\D","").Length -le 3} returns the files that I need to rename. The whole command I used was

Get-ChildItem | Where {($_.Name -replace "\D","").Length -le 3} | Rename-Item -NewName { $_.Name -replace "Test ","Test 0"}

Its also possible to rename all files to an number-only scheamtic and use the padleft command as shown here

Upvotes: 2

Related Questions