devklick
devklick

Reputation: 2629

Batch file to unzip and rename files

I have a batch file which unzips archives from within a directory, and renames the extracted files. The contents of my batch file are:

for /F %%I IN ('dir /b /s *.zip *.rar') DO (
"C:\Program Files\7-Zip\7z.exe" x -o"%%~dpI" "%%I" -aoa
 ) 
 DEL *.zip
 @echo off
 set i=1
 for %%f in (*.xml) do call :renameit "%%f"
 goto done

 :renameit
 ren %1 FileName%i%_Msd.xml
 set /A i+=1

 :done

I expect the files to be renamed as

 FileName1.xml
 FileName2.xml
 FileName3.xml
 ...

However, the renamed file names seem to start from 2 instead of 1. If I re-run the batch file after it has initially extracted and incorrectly renamed starting from 2, it corrects this naming error and starts from one.

How can I correct this so as the renamed files correctly start from 1?

Upvotes: 0

Views: 3018

Answers (1)

Squashman
Squashman

Reputation: 14290

An explanation for you and if you would have watched your CODE execute you would have seen this PLAIN as day.

The FOR command is iterating the files in the current folder one file at a time. So for example if you have three files in your folder named A.txt, B.txt and Z.txt, the FOR command first processes A.txt and renames it to File1.txt. It then sees B.txt because it is the next file alphabetically and renames it to File2.txt. Now because you renamed A.txt to File1.txt, it sees this file next and renames it to File3.txt. After that it sees Z.txt and renames it too File4.txt. So the problem is not with your counter variable, it is how the FOR command processes the files in the folder.

Now if you test this code.

@echo off
dir /b *.txt

set i=1
for %%f in (*.txt) do call :renameit "%%f"
pause
GOTO :EOF

:renameit
@ECHO ON
ren %1 FileName%i%.txt
@ECHO OFF
set /A i+=1

Your output will look like this.

A.txt
B.txt
Z.txt

C:\test>ren "A.txt" FileName1.txt

C:\test>ren "B.txt" FileName2.txt

C:\test>ren "FileName1.txt" FileName3.txt

C:\test>ren "Z.txt" FileName4.txt
Press any key to continue . . .

Now if you change to using a FOR /F command to parse the output of the DIR command, you will get your desired result. The DIR command will do all of its processing first before the FOR command takes over and start processing the output.

So changing the code:

@echo off
dir /b *.txt

set i=1
for /F "delims=" %%f in ('dir /a-d /b *.txt') do call :renameit "%%f"
pause
GOTO :EOF

:renameit
@ECHO ON
ren %1 FileName%i%.txt
@ECHO OFF
set /A i+=1

Your output will now be this.

A.txt
B.txt
Z.txt

C:\test>ren "A.txt" FileName1.txt

C:\test>ren "B.txt" FileName2.txt

C:\test>ren "Z.txt" FileName3.txt
Press any key to continue . . .

Upvotes: 2

Related Questions