anandr
Hi all
I have a program that creates series of images named, say, "Photo1.bmp", "Photo2.bmp", etc.
When number of files is more than 10 or 100, there is an issue with sorting these files, because
"Photo10.bmp" appears after "Photo1.bmp" and before "Photo2.bmp":
Code: Select all
C:\TEMP\TEST>dir /b
The same sorting issue arises in the windows explorer.Photo1.bmp
Photo10.bmp
Photo100.bmp
Photo101.bmp
Photo102.bmp
Photo11.bmp
Photo12.bmp
Photo13.bmp
Photo2.bmp
Photo3.bmp
Photo4.bmp
Photo5.bmp
Photo6.bmp
Photo7.bmp
Photo8.bmp
Photo9.bmp
I need to rename these files adding padding zeros like this (more padding zeros is also OK):
I tried to write a batch file that scans sequentially through one-, two-, three-digit files and adds padding zeroes.Photo001.bmp
Photo002.bmp
Photo003.bmp
Photo004.bmp
Photo005.bmp
Photo006.bmp
Photo007.bmp
Photo008.bmp
Photo009.bmp
Photo010.bmp
Photo011.bmp
Photo012.bmp
Photo013.bmp
Photo100.bmp
Photo101.bmp
Photo102.bmp
But I stuck with unexpected behavior of the file mask in DIR command.
To be short here is a batch file that presents it:
Code: Select all
@Echo off
rem % 1 file prefix
rem % 2 file extension
Echo One-digit files:
FOR /F %%i IN ('dir /b %~1?.%~2') DO @( Echo %%i )
Echo.
Echo Two-digit files:
FOR /F %%i IN ('dir /b %~1??.%~2') DO @( Echo %%i )
Echo.
Echo Three-digit files:
FOR /F %%i IN ('dir /b %~1???.%~2') DO @( Echo %%i )
Echo.
C:\TEMP\TEST>RenameFilesTo_6digits.cmd Photo bmp
I have the following output:
I can not understand, why dir /b Photo?.bmp matches "Photo1.bmp" ... "Photo9.bmp", butOne-digit files:
Photo1.bmp
Photo2.bmp
Photo3.bmp
Photo4.bmp
Photo5.bmp
Photo6.bmp
Photo7.bmp
Photo8.bmp
Photo9.bmp
Two-digit files:
Photo1.bmp
Photo10.bmp
Photo11.bmp
Photo12.bmp
Photo13.bmp
Photo2.bmp
Photo3.bmp
Photo4.bmp
Photo5.bmp
Photo6.bmp
Photo7.bmp
Photo8.bmp
Photo9.bmp
Three-digit files:
Photo1.bmp
Photo10.bmp
Photo100.bmp
Photo101.bmp
Photo102.bmp
Photo11.bmp
Photo12.bmp
Photo13.bmp
Photo2.bmp
Photo3.bmp
Photo4.bmp
Photo5.bmp
Photo6.bmp
Photo7.bmp
Photo8.bmp
Photo9.bmp
dir /b Photo??.bmp matches not just two-digit files, but also one-digit ones: "Photo1.bmp" ... "Photo9.bmp"?
Does anybody have an explanation of this?
I'm using WinXP SP2 PRO
C:\TEMP\TEST>ver
Microsoft Windows XP [Version 5.1.2600]
P.S.
It would be nice if someone can suggest a better idea how to rename such sequence of files.
By the way, sorting them in creation/modification order do not always work,
because some of them should be processed by other programs,
so their creation/modification time is altered.
Last edited by anandr (14 Jan 2010 15:08)
Everything will be OK at the end. If it is not OK -- it is not the end.
----------------------------
#2 14 Jan 2010 19:14
bluesxman
Yeah I don't think you will get around that easily, so a different approach is probably advisable.
How about something like this instead?
Code: Select all
@echo off
set "prefix=%~1"
set "ext=%~2"
set "pad.length=6"
set "pad="
for /l %%a in (0,1,%pad.length%) do call set "pad=%%pad%%0"
for /f "usebackq tokens=*" %%a in (`dir /b "%prefix%*.%ext%"`) do (
set "number=%%~na"
call set "number=%pad%%%number:%prefix%=%%"
call set "newname=%prefix%%%number:~-%pad.length%%%%%~xa
call rename "%%~a" "%%newname%%"
)
pause
cmd | *sh | ruby | chef
----------------------------
#3 15 Jan 2010 14:10
Drewfus
anandr,
try this;
Code: Select all
@echo off
setlocal
for /F %%A in ('dir /B Photo*.bmp') do call :bmp %%~nA
goto :eof
:bmp
set bmp=%*
set bmp=%bmp:Photo=%
set bmp=000%bmp%
ren %*.bmp Photo%bmp:~-4%.bmp
goto :eof
dir /B *.bmp | sort
----------------------------
#4 15 Jan 2010 15:01
bluesxman
Er Drewfus, you've just used the same basic method as I suggested, but implemented it in a less flexible and robust way hmm
cmd | *sh | ruby | chef
----------------------------
#5 15 Jan 2010 16:36
anandr
Thank you both, bluesxman and Drewfus, for your replies.
I agree with bluesxman that his solution is more flexible.
Still, what's wrong with the file mask in DIR command?
Is this another example how MS makes documentation that reflects how things should work instead of how things really work?
Just one more question concerning the script: sometimes I have files named like this: "1.jpg", "2.jpg", ..., "10.jpg", "11.jpg", "1.jpg".
In this case file prefix is empty.
I tried to handle this and here is a script which satisfies me by 99.9%.
I'm only 99.9% satisfied with it, because I can not figure out how to treat "0.jpg" file in such sequence, so I'm checking for it presence manually, not through the main loop.
May be someone has an idea how to do this in nicer way?
Code: Select all
@echo off
@setlocal enabledelayedexpansion
set "Pad.Length.Default=6"
:: no parameters at all -- print usage and exit
if [%~1%~2%~3] EQU [] goto PrintUsage
:: one parameter only -- print usage and exit
if [%~2%~3] EQU [] goto PrintUsage
set "Prefix=%~1"
set "Ext=%~2"
set "Pad.Length=%~3"
if [%Pad.Length%] EQU [] call set "Pad.Length=%%Pad.Length.Default%%"
set "Pad="
for /l %%a in (0,1,%Pad.Length%) do call set "Pad=%%Pad%%0"
::DEBUG: Echo Pad = "%Pad%"
::DEBUG: Echo Prefix = "%Prefix%"
::DEBUG: Echo Ext = "%Ext%"
::DEBUG: Echo Pad.Length.Default = "%Pad.Length.Default%"
::DEBUG: Echo Pad.Length = "%Pad.Length%"
if [%Prefix%] EQU [] goto ProcessEmptyPrefix
:ProcessNonEmptyPrefix
for /f "usebackq tokens=*" %%a in (`dir /b "%Prefix%*.%Ext%"`) do (
set "Number=%%~na"
call set "Number=%Pad%%%Number:%Prefix%=%%"
call set "NewName=%Prefix%%%Number:~-%Pad.Length%%%%%~xa"
call Echo renaming "%%~a" "%%NewName%%"
call rename "%%~a" "%%NewName%%"
)
goto :EOF
:ProcessEmptyPrefix
:: Currently I have no idea how to handle "0.%Ext%" file automatically, so
IF exist "0.%Ext%" (
call set "Number=%Pad%"
call set "NewName=%%Number:~-%Pad.Length%%%.%%Ext%%"
call Echo renaming "0.%%Ext%%" "%%NewName%%"
call rename "0.%%Ext%%" "%%NewName%%"
)
for /f "usebackq tokens=*" %%a in (`dir /b "*.%Ext%"`) do (
set "Number=%%~na"
SET /A NextNumber=1 + Number
SET /A AnotherNumber=NextNumber + Number
:: Uncomment next line to see which files are accepted
::DEBUG: Echo Number = "!Number!"; NextNumber = "!NextNumber!"; AnotherNumber = "!AnotherNumber!"; If NextNumber ^< AnotherNumber -- then we have number-named file
IF !NextNumber! LSS !AnotherNumber! (
call set "Number=%Pad%%%Number%%"
call set "NewName=%%Number:~-%Pad.Length%%%%%~xa"
call Echo renaming "%%~a" "%%NewName%%"
call rename "%%~a" "%%NewName%%"
)
)
:PrintUsage
Echo.
Echo This script scans current directory for files named "<FilePrefix>#.<Extension>" (# is a number)
Echo and adds padding zeros to the number.
Echo.
Echo Usage:
Echo %~n0 ^<FilePrefix^> ^<Extension^> [^<PaddingLength^>]
Echo.
Echo If ^<PaddingLength^> is omitted, then default value "%Pad.Length.Default%" is used.
Echo.
Echo To process files without prefix (like "1.jpg", "2.jpg", "13.jpg", etc.), run the script like this:
Echo %~n0 "" ^<Extension^> [^<PaddingLength^>]
goto :EOF
Everything will be OK at the end. If it is not OK -- it is not the end.
----------------------------
#6 15 Jan 2010 17:33
bluesxman
Amending my own code (shouldn't be too difficult to shoehorn this back into yours):
Code: Select all
@echo off
set "prefix=%~1"
set "ext=%~2"
set "pad.length=6"
set "pad="
for /l %%a in (0,1,%pad.length%) do call set "pad=%%pad%%0"
for /f "usebackq tokens=*" %%a in (`dir /b "%prefix%*.%ext%"`) do (
set "number=%%~na"
REM pad to 6 characters
if defined prefix (call set "number=%pad%%%number:%prefix%=%%") ELSE (call set "number=%pad%%%number%%")
call set "newname=%prefix%%%number:~-%pad.length%%%%%~xa
call echo:rename "%%~a" "%%newname%%"
)
pause
As for "dir" behaviour, I can see what it's doing -- it's treating "?" as zero or one occurrence of any character, in much the same way that "*" matches zero or any number of occurrences of any character:
Code: Select all
D:\My Documents\Scripts\ss64>dir Photo?.bmp
Volume in drive D is Data
Volume Serial Number is EF78-7FFA
Directory of D:\My Documents\Scripts\ss64
15/01/2010 16:29 0 Photo.bmp
15/01/2010 16:29 0 Photo1.bmp
2 File(s) 0 bytes
0 Dir(s) 10,290,286,592 bytes free
D:\My Documents\Scripts\ss64>dir Photo*.bmp
Volume in drive D is Data
Volume Serial Number is EF78-7FFA
Directory of D:\My Documents\Scripts\ss64
15/01/2010 16:29 0 Photo.bmp
15/01/2010 16:29 0 Photo1.bmp
15/01/2010 16:29 0 Photo10.bmp
2 File(s) 0 bytes
0 Dir(s) 10,290,286,592 bytes free
D:\My Documents\Scripts\ss64>
----------------------------
#7 15 Jan 2010 17:38
avery_larry
? wildcard doesn't always work like expected. It has quirks:
https://ss64.com/nt/syntax-wildcards.html
----------------------------
#8 15 Jan 2010 18:52
anandr
Thank you for the suggestion, bluesxman. I really like it
It seems that it has not just quirks, but QUIRKS.avery_larry wrote:
? wildcard doesn't always work like expected. It has quirks:
http://ss64.com/nt/syntax-wildcards.html
First I create several files with this batch file:
Code: Select all
Copy %0 Photo0.bmp
Copy %0 Photo1.bmp
Copy %0 Photo2.bmp
Copy %0 Photo3.bmp
Copy %0 Photo10.bmp
Copy %0 Photo11.bmp
Copy %0 Photo12.bmp
Copy %0 Photo13.bmp
Copy %0 Photo100.bmp
Copy %0 Photo101.bmp
Copy %0 Photo102.bmp
Copy %0 Photo103.bmp
Copy %0 Photo1000.bmp
Copy %0 Photo1001.bmp
Copy %0 Photo1002.bmp
Copy %0 Photo1003.bmp
Copy %0 Photo10000.bmp
Copy %0 Photo10001.bmp
Copy %0 Photo10002.bmp
Copy %0 Photo10003.bmp
Copy %0 Photo100000.bmp
Copy %0 Photo100001.bmp
Copy %0 Photo100002.bmp
Copy %0 Photo100003.bmp
Copy %0 Photo0_Suffix.bmp
Copy %0 Photo1_Suffix.bmp
Copy %0 Photo2_Suffix.bmp
Copy %0 Photo3_Suffix.bmp
Copy %0 Photo10_Suffix.bmp
Copy %0 Photo11_Suffix.bmp
Copy %0 Photo12_Suffix.bmp
Copy %0 Photo13_Suffix.bmp
Copy %0 Photo100_Suffix.bmp
Copy %0 Photo101_Suffix.bmp
Copy %0 Photo102_Suffix.bmp
Copy %0 Photo103_Suffix.bmp
Copy %0 Photo1000_Suffix.bmp
Copy %0 Photo1001_Suffix.bmp
Copy %0 Photo1002_Suffix.bmp
Copy %0 Photo1003_Suffix.bmp
Copy %0 Photo10000_Suffix.bmp
Copy %0 Photo10001_Suffix.bmp
Copy %0 Photo10002_Suffix.bmp
Copy %0 Photo10003_Suffix.bmp
Copy %0 Photo100000_Suffix.bmp
Copy %0 Photo100001_Suffix.bmp
Copy %0 Photo100002_Suffix.bmp
Copy %0 Photo100003_Suffix.bmp
Code: Select all
dir *.bmp /o:n /b
Then I execute another batch file testing ? wildcard:Photo0.bmp
Photo0_Suffix.bmp
Photo1.bmp
Photo1_Suffix.bmp
Photo10.bmp
Photo10_Suffix.bmp
Photo100.bmp
Photo100_Suffix.bmp
Photo1000.bmp
Photo1000_Suffix.bmp
Photo10000.bmp
Photo10000_Suffix.bmp
Photo100000.bmp
Photo100000_Suffix.bmp
Photo100001.bmp
Photo100001_Suffix.bmp
Photo100002.bmp
Photo100002_Suffix.bmp
Photo100003.bmp
Photo100003_Suffix.bmp
Photo10001.bmp
Photo10001_Suffix.bmp
Photo10002.bmp
Photo10002_Suffix.bmp
Photo10003.bmp
Photo10003_Suffix.bmp
Photo1001.bmp
Photo1001_Suffix.bmp
Photo1002.bmp
Photo1002_Suffix.bmp
Photo1003.bmp
Photo1003_Suffix.bmp
Photo101.bmp
Photo101_Suffix.bmp
Photo102.bmp
Photo102_Suffix.bmp
Photo103.bmp
Photo103_Suffix.bmp
Photo11.bmp
Photo11_Suffix.bmp
Photo12.bmp
Photo12_Suffix.bmp
Photo13.bmp
Photo13_Suffix.bmp
Photo2.bmp
Photo2_Suffix.bmp
Photo3.bmp
Photo3_Suffix.bmp
Code: Select all
@Echo off
Echo.
Echo 1-digit files
Echo =============
dir Photo?.bmp /O:N /B
Echo.
dir Photo?_Suffix.bmp /O:N /B
Echo.
Echo 2-digit files
Echo =============
dir Photo??.bmp /O:N /B
Echo.
dir Photo??_Suffix.bmp /O:N /B
Echo.
Echo 3-digit files
Echo =============
dir Photo???.bmp /O:N /B
Echo.
dir Photo???_Suffix.bmp /O:N /B
Echo.
Echo 4-digit files
Echo =============
dir Photo????.bmp /O:N /B
Echo.
dir Photo????_Suffix.bmp /O:N /B
Echo.
Echo 5-digit files
Echo =============
dir Photo?????.bmp /O:N /B
Echo.
dir Photo?????_Suffix.bmp /O:N /B
Echo.
Echo 6-digit files
Echo =============
dir Photo??????.bmp /O:N /B
Echo.
dir Photo??????_Suffix.bmp /O:N /B
Echo.
Echo 7-digit files
Echo =============
dir Photo???????.bmp /O:N /B
Echo.
dir Photo???????_Suffix.bmp /O:N /B
It makes me really mad to see "Photo1000.bmp" among "3-digit files".1-digit files
=============
Photo0.bmp
Photo1.bmp
Photo2.bmp
Photo3.bmp
Photo0_Suffix.bmp
Photo1_Suffix.bmp
Photo2_Suffix.bmp
Photo3_Suffix.bmp
2-digit files
=============
Photo0.bmp
Photo1.bmp
Photo10.bmp
Photo11.bmp
Photo12.bmp
Photo13.bmp
Photo2.bmp
Photo3.bmp
Photo10_Suffix.bmp
Photo11_Suffix.bmp
Photo12_Suffix.bmp
Photo13_Suffix.bmp
3-digit files
=============
Photo0.bmp
Photo0_Suffix.bmp
Photo1.bmp
Photo10.bmp
Photo100.bmp
Photo1000.bmp
Photo1001.bmp
Photo1002.bmp
Photo1003.bmp
Photo101.bmp
Photo102.bmp
Photo103.bmp
Photo11.bmp
Photo12.bmp
Photo13.bmp
Photo2.bmp
Photo2_Suffix.bmp
Photo3.bmp
Photo3_Suffix.bmp
Photo100_Suffix.bmp
Photo101_Suffix.bmp
Photo102_Suffix.bmp
Photo103_Suffix.bmp
4-digit files
=============
Photo0.bmp
Photo0_Suffix.bmp
Photo1.bmp
Photo10.bmp
Photo100.bmp
Photo1000.bmp
Photo1001.bmp
Photo1002.bmp
Photo1003.bmp
Photo101.bmp
Photo102.bmp
Photo103.bmp
Photo11.bmp
Photo12.bmp
Photo13.bmp
Photo2.bmp
Photo2_Suffix.bmp
Photo3.bmp
Photo3_Suffix.bmp
Photo1000_Suffix.bmp
Photo1001_Suffix.bmp
Photo1002_Suffix.bmp
Photo1003_Suffix.bmp
5-digit files
=============
Photo0.bmp
Photo0_Suffix.bmp
Photo1.bmp
Photo10.bmp
Photo100.bmp
Photo1000.bmp
Photo10000.bmp
Photo10001.bmp
Photo10002.bmp
Photo10003.bmp
Photo1001.bmp
Photo1002.bmp
Photo1003.bmp
Photo101.bmp
Photo102.bmp
Photo103.bmp
Photo11.bmp
Photo12.bmp
Photo13.bmp
Photo2.bmp
Photo2_Suffix.bmp
Photo3.bmp
Photo3_Suffix.bmp
Photo10000_Suffix.bmp
Photo10001_Suffix.bmp
Photo10002_Suffix.bmp
Photo10003_Suffix.bmp
6-digit files
=============
Photo0.bmp
Photo0_Suffix.bmp
Photo1.bmp
Photo10.bmp
Photo100.bmp
Photo1000.bmp
Photo10000.bmp
Photo100000.bmp
Photo100001.bmp
Photo100002.bmp
Photo100003.bmp
Photo10001.bmp
Photo10002.bmp
Photo10003.bmp
Photo1001.bmp
Photo1002.bmp
Photo1003.bmp
Photo101.bmp
Photo102.bmp
Photo103.bmp
Photo11.bmp
Photo12.bmp
Photo13.bmp
Photo2.bmp
Photo2_Suffix.bmp
Photo3.bmp
Photo3_Suffix.bmp
Photo100000_Suffix.bmp
Photo100001_Suffix.bmp
Photo100002_Suffix.bmp
Photo100003_Suffix.bmp
7-digit files
=============
Photo0.bmp
Photo0_Suffix.bmp
Photo1.bmp
Photo10.bmp
Photo100.bmp
Photo1000.bmp
Photo10000.bmp
Photo100000.bmp
Photo100001.bmp
Photo100002.bmp
Photo100003.bmp
Photo10001.bmp
Photo10002.bmp
Photo10003.bmp
Photo1001.bmp
Photo1002.bmp
Photo1003.bmp
Photo101.bmp
Photo102.bmp
Photo103.bmp
Photo11.bmp
Photo12.bmp
Photo13.bmp
Photo2.bmp
Photo2_Suffix.bmp
Photo3.bmp
Photo3_Suffix.bmp
File Not Found
I can not understand how
Code: Select all
dir Photo???.bmp /O:N /B
Anyway, as one can see ? works OK if it is not at the end of file name.
Only now I fully understand full meaning of this phrase (https://ss64.com/nt/syntax-wildcards.html):
The ? wildcard will match a single character (or a NULL at the end of a filename)
The case is closed. Thanks everyone for their attention and assistance.
Perhaps it might be a good idea to expand description of the ? wildcard a little bit with few more examples like the ones above.
Last edited by anandr (15 Jan 2010 18:56)