0

I would like to rename a bunch of files in a given directory that are already present in ascending order to another line of consecutive ascending numbers. The goal is to close gaps in between and get rid of the preceding zeros.

For example, original files are named:

0,1,2,4,9  

The output in this case should be:

1,2,3,4,5

Since I want to put them in the same folder, which creates a conflict as the filenames are partly the same. To solve this, I first renamed them to:

a(1,2,3,4,5) 

and then back to the numeric expression as before. This works up to a number of 9 files but as I have more than 9 files in some directories, it creates another problem as the filenames are no integer I suppose, so for example, if I have the files:

1,6,11 

the file 11 will be in second position and gets renamed to 2 instead of 3.

My script looks like this:

@echo off
setlocal enabledelayedexpansion
set /a count=1
for /f "tokens=*" %%A in ('dir /b *.png') do (
    ren "%%a" a!count!.png
    set /a count+=1
)
set /a count=1
for /f "tokens=*" %%A in ('dir /b *.png') do (
    ren "%%a" !count!.png
    set /a count+=1
)

Is it possible to adopt this so that the filenames are recognized as integers and 2-digit numbers will be recognized as such?

3 Answers 3

1

It's much simpler to do that in PowerShell:

$c = 0; ls *.png | sort |% { ren $_ -Ne ("a{0:d3}.png" -f $c); $c++ }
ls a*.png | ren -ne { $_.Name -replace '^a' }

Below is the full unaliased version of the above. {0:d3} is the argument to .NET's String.Format which is one of the ways to print a number with zero padding

$count = 0
# Rename the file with 'a' prefix plus increasing count
Get-ChildItem -Path *.png | Sort-Object | ForEach-Object {
    Rename-Item $_ -NewName ("a{0:d3}.png" -f $c)
    $count++
}

# Remove the 'a' prefix from names by doing a regex replace
Get-ChildItem -Path a*.png | Rename-Item -NewName { $_.Name -replace '^a', '' }

Doing this in batch is more cumbersome, as like almost anything else in cmd. Anyway you can simplify the second rename round by using a suffix instead of prefix so that it's easier to remove with the ren command using wildcard in case all file names have fixed length. This way you don't need another for loop

One important note: you must sort the dir output just like what I did in PowerShell above, because dir in cmd doesn't sort anything and just list files in whatever order the filesystem driver returns. In NTFS you're lucky because the directory entries are stored in a B-tree which is almost sorted for most inputs, but it's not guaranteed at all.

@echo off
setlocal enabledelayedexpansion
set /a count=1
for /f "tokens=*" %%a in ('dir /o /b *') do (
    set num=00%%a
    set num=!num:~-3!
    ren "!num!" !count!.png.a
    set /a count+=1
)

rem Remove the .a suffix
ren ???.png.a ???.png
Sign up to request clarification or add additional context in comments.

1 Comment

The on topic code you have posted is trying, and failing, to perform the requested task. The rest of the code i.e. PowerShell, is off topic and has no place under this question without modification to match the [batch-file] question tag. As it stands your answer therefore appears to be an attempt at pushing your personal choice of scripting language over that of the OP's. Using the OP's example filenames, 1.png, 6.png and 11.png, your for /F loop is attempting, three times, to rename a file from png, to 1.png.a, 2.png.a and 3.png.a!
1

If the number of files is greater than 9, the new names must have two digits (with left zeros from 1 to 9) to keep the original order. This solution do that:

@echo off
setlocal EnabledDelayedExpansion

rem First create a rename array with file names sorted in the right order
set /a count=0
for /f "delims=" %%a in ('dir /b *.png') do (
    set /A index=100+%%~Na, count+=1
    set "rename[!index!]=%%a"
)

rem If the number of files is > 9: put two digits (left zero) in new name
if %count% gtr 9 (set base=100) else set base=10

rem Do the rename
for /F "tokens=2 delims==" %%n in ('set rename') do (
   set /A base+=1
   ren %%n !base:~1!.new
)
ren *.new *.png

1 Comment

At the very least you should, for safety, change set rename to set rename[. However, I'd also advise an earlier command to undefine any possible existing variables in the current environment with names beginning with that substring too.
0
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

rem I use "u:\your files" as a test directory. Switch to required directory
PUSHD "u:\your files"

FOR /f %%b IN ('dir /b /a-d *.png') DO SET ofilename=%%~nb&IF "!ofilename:~1!"=="" (REN "%%b" "10%%b") ELSE (REN "%%b" "1%%b")
FOR /f "tokens=1*delims=:" %%b IN ('dir /b /on /a-d *.png^|findstr /N "."') DO REN "%%c" "%%b.png"

POPD

GOTO :EOF

I'm assuming that your directory originally contains only filenames that are 1 or 2 digits and there are no instances of smth like "7.png" and "07.png"

The first 'forrenames the files as 3-digit names by prexing the current name with10for 1-digit names and1` for 2-digit names

0 1 2 4 6 9 11 26 becomes 100 101 102 104 106 109 111 126

The second for first sorts the dir list in name order (/on) then numbers each line of the result using findstr /n, yielding 1:100 2:101 3:102 4:104 5:106 6:109 7:111 8:126

Then for applies "tokens=1*delims=:" to the list, tokenising on : and applying the line number to %%b and current filename to %%c. Rename using these values, job done.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.