REN and FOR %a with files

Jun 7, 2008
121
0
#1
Hi

Running TCC 13.02.35 Windows XP [Version 5.1.2600]

1. Create 3 files with names

20111129.PR2
20111130.PR2
20111128.PR2

in an empty directory. They are non-zero in size.

2. Now do
for %a in (*.pr2) do ren %a B%a

3. I find that the for loop runs 4 times. It does the renaming for the 3 files and then does the 1st file again. I see

B20111129.PR2
B20111130.PR2
BB20111128.PR2

Anyone reproduce this ?

thanks

Stephen Howe
 
Jan 19, 2011
581
10
Norman, OK
#2
Anyone reproduce this ?
Interesting. I tried it first just using zero size files 1.txt, 2.txt, and 3.txt and it worked fine, renaming just the three files. When I used your example verbatim, I got the same problem you got.

HTML:
[C:\BIN\temp]
09:22:52 $ > 1.txt
 
[C:\BIN\temp]
09:22:57 $ > 2.txt
 
[C:\BIN\temp]
09:23:01 $ > 3.txt
 
[C:\BIN\temp]
09:23:04 $ dir
 
Volume in drive C is unlabeled      Serial number is 58b8:a853
Directory of  C:\BIN\temp\*
 
1/06/2012  09:23        <DIR>    .
1/06/2012  09:23        <DIR>    ..
1/06/2012  09:22              0  1.txt
1/06/2012  09:23              0  2.txt
1/06/2012  09:23              0  3.txt
                0 bytes in 3 files and 2 dirs
    33,034,014,720 bytes free
 
[C:\BIN\temp]
09:23:05 $ for %i in (*.txt) do ren %i 1%i
C:\BIN\temp\1.txt -> C:\BIN\temp\11.txt
    1 file renamed
C:\BIN\temp\2.txt -> C:\BIN\temp\12.txt
    1 file renamed
C:\BIN\temp\3.txt -> C:\BIN\temp\13.txt
    1 file renamed
 
[C:\BIN\temp]
09:23:31 $ > 20111129.PR2
 
[C:\BIN\temp]
09:23:53 $ > 20111130.PR2
 
[C:\BIN\temp]
09:24:00 $ > 20111128.PR2
 
[C:\BIN\temp]
09:24:05 $ for %a in (*.pr2) do ren %a B%a
C:\BIN\temp\20111128.PR2 -> C:\BIN\temp\B20111128.PR2
    1 file renamed
C:\BIN\temp\20111129.PR2 -> C:\BIN\temp\B20111129.PR2
    1 file renamed
C:\BIN\temp\20111130.PR2 -> C:\BIN\temp\B20111130.PR2
    1 file renamed
C:\BIN\temp\B20111128.PR2 -> C:\BIN\temp\BB20111128.PR2
    1 file renamed
 
[C:\BIN\temp]
09:24:29 $ ver
 
TCC  13.03.36  Windows XP [Version 5.1.2600]
 
#3
I know that TCC LE is not supported here, but here's a screen dump:

Code:
[c:\tmpx] > ver
 
TCC LE  13.03.36  Windows 7 [Version 6.1.7601]
 
[c:\tmpx] > for %f in ( 28.pr2 30.pr2 29.pr2 ) do echo hello >%f
 
[c:\tmpx] > dir /hklm *.pr2
2012-01-06  9:32              7  28.pr2
2012-01-06  9:32              7  29.pr2
2012-01-06  9:32              7  30.pr2
 
[c:\tmpx] > for %a in ( *.pr2 ) do ren %a B%a
C:\tmpx\28.pr2 -> C:\tmpx\B28.pr2
    1 file renamed
C:\tmpx\29.pr2 -> C:\tmpx\B29.pr2
    1 file renamed
C:\tmpx\30.pr2 -> C:\tmpx\B30.pr2
    1 file renamed
C:\tmpx\B28.pr2 -> C:\tmpx\BB28.pr2
    1 file renamed
 
[c:\tmpx] > dir /hklm *.pr2
2012-01-06  9:32              7  b29.pr2
2012-01-06  9:32              7  b30.pr2
2012-01-06  9:32              7  bb28.pr2
 
#4
The phenomenon is an artifact of wildcard expansion. It has been a CAVEAT for renamin, moving, or copying by any program which obtains the names of files to be processed from the file system one-at-a-time that if the result of command action matches the input criteria, it may be acted on more than once.
AFAIK all programs for the PC environment behave this way. Cf: Most POSIX-compatible shells expand wildcards before processing the first match, so they do not have this issue.
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
3,724
47
Albuquerque, NM
prospero.unm.edu
#5
In the full TCC, you can work around this issue by using REN /O:A to generate the list of files to be renamed before beginning the actual operation. I don't think that option is available in TCC/LE, though.
 
#6
Stephen, if you do not have full TCC, as a workaround you can use renx.btm, a batch file I wrote several years ago, which calls Perl to do its file renaming.

Since it's a batch file, I will post the file in the "Tips and Tricks > Scripting" forum, not here . . .

Eric
 
Jul 1, 2008
81
0
71
Montreal
#7
In the full TCC, you can work around this issue by using REN /O:A to generate the list of files to be renamed before beginning the actual operation. I don't think that option is available in TCC/LE, though.
Good idea. For a long time I have tailored such constructs to avoid the problem. For example I might have written Stephen's code as
Code:
for %a in (2*.pr2) do ren %a B%a
but this is more challenging when filenames are not similar. Your suggestion offers an easier approach.

Peter
 
Jun 7, 2008
121
0
#8
Good idea. For a long time I have tailored such constructs to avoid the problem. For example I might have written Stephen's code as
Code:
for %a in (2*.pr2) do ren %a B%a
but this is more challenging when filenames are not similar. Your suggestion offers an easier approach.
Peter
That is exactly what I wound up doing. No ambiguity.
I have the full version of TCC and Take Command, not TCC/LE. Been using JPSoft's command processors since 4DOS 3.0.

Thanks all

Stephen Howe
 
#9
In the full TCC, you can work around this issue by using REN /O:A to generate the list of files to be renamed before beginning the actual operation. I don't think that option is available in TCC/LE, though.
Would /o:u be faster, esp. when the file system does not keep the directory sorted? Of course, the difference would be in the sub-second range, insignificant under virtually all conditions...