7

I've got a bunch of files named as:

01. Filename.ext
02. Filename.ext
03. Filename.ext
etc.

I need to batch rename them with PowerToys PowerRename by increasing the number in the beginning of the file name by a specific value, say 15, so that their names become, for example:

16. Filename.ext
17. Filename.ext
18. Filename.ext
etc.

As far as I understand I should use Regular Expressions for this task. Unfortunately it is all I understand regarding this matter.

So I'm asking your help with this exact task: what to put into the "Search for:" and "Replace with:" fields?

harrymc
  • 498,455
YKKY
  • 267

4 Answers4

4

The PowerShell option:

$Increment = 15
Get-ChildItem | Where Name -match '^(\d+)(.+)$' |
    Select FullName,
           @{ N = 'Index'    ; E = { [Int]$Matches[1] }},
           @{ N = 'NameText' ; E = { $Matches[2] }} |
Sort Index -Descending | ForEach{    
    Rename-Item $_.FullName -NewName ( '{0:d2}{1}' -f ( $_.Index + $Increment ), $_.NameText ) }

Breaking it down:

  • The -match operator uses regular expression matching, returns a boolean value & populates the $Matches Automatic Variable. The regular expression '^(\d+)(.+)$' will match any string beginning with one or more digits and at least one character following those digits and generate two capture groups, the leading digits in the first and all subsequent text in the second:
PS C:\>>'01. FileName.txt' -match '^(\d+)(.+)$'
True
PS C:\> $matches

Name Value


2 . FileName.txt 1 01 0 01. FileName.txt

PS C:\>'{0:d2}{1}' -f 7, '. FileNaem.txt'
07. FileNaem.txt
  • The Rename-Item Cmdlet's -NewName parameter can be either a string or a scriptblock, the scriptblock allowing the new name to be based on the values in the current $Matches variable:
 { '{0:d2}{1}' -f ( $Increment + $matches[1] ), $matches[2] }
Keith Miller
  • 10,694
  • 1
  • 20
  • 35
3

PowerRename is not the right tool for this type of complex rename. A more powerful tool is Bulk Rename Utility, free for personal use.

For example, I combine below the operations of:

  1. Remove the first two characters
  2. Prepend an incrementing number starting from 16

enter image description here

harrymc
  • 498,455
1

// Edit

Inspired by @Keith Miller's idea of ​​using a descending/reverse loop to rename files in cmd/bat:

set "_n=" & set "_c=" & <nul (for /l %i in (99 -1 16)do set/a "_c=100%~i-15, _n=100%~i" && cmd/v/c "ren "!_c:~-2!.*.ext" "!_n:~-2!.*.ext"")

To do the same in PowerShell:

$i=(ls *.ext).count+16 ; For($i -eq 15; $i--) {
  $old=($i-15).ToString("00") ; ls $($old+'. *.ext')|
  % {ren $_ -new ($_.Name.Replace("$old. ","$i. "))}}

Edit //


set "_n=" & for /l %i in (1 1 84)do @set "_n=00%~i" && @cmd/v/c "ren "!_n:~-2!.*.ext" "!_n:~-3!.*.ext""
set "_n=" & set "_c=" & >nul (for /l %i in (1 1 84)do @set/a "_c=1000%~i+15" && @set/a "_n=1000+%~i" && @cmd/v/c "ren "!_n:~-3!.*.ext" "!_c:~-2!.*.ext"")

You can do this in command line too:

Obs.:1. Assuming that when renaming two-digit numbers

Obs.:2. Your folder has a total of 84 files = 100 - 16

Obs.:3. All files have the same extension.

1. First, add a digit to each file, renaming 16. file.ext -> 016. file.ext, thus avoiding conflict when renaming 01. file.ext for the name of 16. file.ext (existing file)

set "_n=" & for /l %i in (1 1 84)do @set "_n=00%~i" && @cmd/v/c "ren "!_n:~-2!.*.ext" "!_n:~-3!.*.ext""

Obs.:4. Use For /L loop from 1 to 84, define _n=001, when adding 00, in the front variable %i, a substring of maximum length 2 (file source "!_n:~-2!.*.ext") and a substring of maximum length 3 (file target "!_n:~-3!.*.ext") will be used by ren for rename your files in loop:

2. Use again a For /L loop from 1 to 84, define _c=1000%~i+15, when adding 1000, adding to the variable %i, a substring of maximum length 3 (file source "!_c:~-3!.*.ext") and a substring of maximum length 3 (file target "!_n:~-2!.*.ext") will be used by ren for rename your files in loop:

for /l %i in (1 1 84)do @set/a "_c=1000%~i+15" && @set/a "_n=1000+%~i" && @cmd/v/c "ren "!_n:~-3!.*.ext" "!_c:~-2!.*.ext""

Obs.:5. The result in the loop will be from 1 to 84:

ren 001.file.ext 16.file.ext
ren 002.file.ext 17.file.ext
ren 003.file.ext 18.file.ext
    ...
ren 084.file.ext 99.file.ext

Obs.:6. This can easily be expanded to 1 to 840, 1 to 8400, ...:

for /l %i in (1 1 840)do ...
 ...  set "_n=000%~i" 
 ...  cmd/v/c "ren "!_n:~-3!.*.ext" "!_n:~-4!.*.ext""

for /l %i in (1 1 840)do ... ... set/a "_c=10000%~i+15" ... set/a "_n=10000+%~i" ... cmd/v/c "ren "!_n:~-4!..ext" "!_c:~-3!..ext"")


The same in Bat/CMD:

@echo off && cd /d "%~dp0"

set "_n=" & for /l %%i in (1 1 84 )do set "_n=00%%~i" && cmd/v/c "ren "!_n:~-2!..ext" "!_n:~-3!..ext""

set "_n=" & set "_c=" & >nul (for /l %%i in (1 1 84 )do set/a "_c=1000%%~i+15, _n=1000+%%~i" && cmd/v/c "ren "!_n:~-3!..ext" "!_c:~-2!..ext"")

Io-oI
  • 9,237
1

PowerRename can do the above task fairly simply,

In this case regex in the 'Search for' can be:

^\d{2}\. 

Replace with:

${padding=2,start=16}. 

I believe this only works with incrementing numbers. Also sometimes files can be left with a (2) at the end because of the order that they are renamed, causing temporary duplicate files during the operation.