Loop anomaly

#1
Is this a bug or a gotcha?

Code like this works:
for /A:d %i in (*.*) do (
if exist %i\jetpdb\ (
del /FSEXY %i\jetpdb\
)
)

for /A:d %i in (*.*) do (
if exist %i\%i.exe (
del /F %i\%i.exe
)
)

But if I combine them into one loop. the second del code is %i.exe code is never executed.

for /A:d %i in (*.*) do (
if exist %i\jetpdb\ (
del /FSEXY %i\jetpdb\
)
if exist %i\%i.exe (
del /F %i\%i.exe
)
)

What gives?
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
3,650
46
Albuquerque, NM
prospero.unm.edu
#2
Is this a bug or a gotcha?

Code like this works:
for /A:d %i in (*.*) do (
if exist %i\jetpdb\ (
del /FSEXY %i\jetpdb\
)
)

for /A:d %i in (*.*) do (
if exist %i\%i.exe (
del /F %i\%i.exe
)
)

But if I combine them into one loop. the second del code is %i.exe code is never executed.

for /A:d %i in (*.*) do (
if exist %i\jetpdb\ (
del /FSEXY %i\jetpdb\
)
if exist %i\%i.exe (
del /F %i\%i.exe
)
)

What gives?
Shouldn't there be a command separator between the two IF commands? And if that doesn't fix the problem, you might check for a DuplicateBugs=Yes directive in your .INI file; if you find it, change the value to No and restart Take Command.

Finally, if this is in a batch file, it would be worthwhile to rewrite your loop using DO instead of FOR.
 
#3
Charles Dye wrote:
| ---Quote (Originally by Roedy)---
|| Is this a bug or a gotcha?
||
|| Code like this works:
|| for /A:d %i in (*.*) do (
|| if exist %i\jetpdb\ (
|| del /FSEXY %i\jetpdb\
|| )
|| )
||
|| for /A:d %i in (*.*) do (
|| if exist %i\%i.exe (
|| del /F %i\%i.exe
|| )
|| )
||
|| But if I combine them into one loop. the second del code is %i.exe
|| code is never executed.
||
|| for /A:d %i in (*.*) do (
|| if exist %i\jetpdb\ (
|| del /FSEXY %i\jetpdb\
|| )
|| if exist %i\%i.exe (
|| del /F %i\%i.exe
|| )
|| )
||
|| What gives?
|| ---End Quote---
| Shouldn't there be a command separator between the two IF commands?
| And if that doesn't fix the problem, you might check for a
| DuplicateBugs=Yes directive in your .INI file; if you find it,
| change the value to No and restart Take Command.
|
| Finally, if this is in a batch file, it would be worthwhile to
| rewrite your loop using DO instead of FOR.

Some other simplifications:
- use ISDIR or ISFILE instead of EXIST, as appropriate, but
- it is not necessary to check whether or not the directory or file
exists before attempting to delete it, just use the /NE option to
suppress error reports if the object to be deleted did not exist:

for /a:d %i in (*) ( del/f/s/ne/x/y %i\jetpdb %+ del/f/ne %i\%i.exe )

--
HTH, Steve
 
#4
On Tue, 03 Nov 2009 11:40:31 -0600, Roedy <> wrote:

|But if I combine them into one loop. the second del code is %i.exe code is never executed.
|
|for /A:d %i in (*.*) do (
|if exist %i\jetpdb\ (
|del /FSEXY %i\jetpdb\
|)
|if exist %i\%i.exe (
|del /F %i\%i.exe
|)
|)
|
|What gives?

A simplified version of the construction works, both at the command line and in
a batch file:

Code:
v:\> for /l %i in (1,1,2) do (
More? if 1 == 1 (
More? echo %i
More? )
More? if 1 == 1 (
More? echo %i
More? )
More? )
1
1
2
2

--
- Vince
 
#5
On Tue, 03 Nov 2009 11:40:31 -0600, Roedy <> wrote:

|But if I combine them into one loop. the second del code is %i.exe code is never executed.
|
|for /A:d %i in (*.*) do (
|if exist %i\jetpdb\ (
|del /FSEXY %i\jetpdb\
|)
|if exist %i\%i.exe (
|del /F %i\%i.exe
|)
|)

Worked here:

Code:
v:\> md foo

v:\> touch /c foo\foo.exe
2009-11-03 14:26:10.743  V:\foo\foo.exe

v:\> for /A:d %i in (*.*) do (
More? if exist %i\jetpdb\ (
More? del /FSEXY %i\jetpdb\
More? )
More? if exist %i\%i.exe (
More? del /F  %i\%i.exe
More? )
More? )
Deleting V:\foo\foo.exe
     1 file deleted
--
- Vince
 
#6
I've bumped into this many times, I still prefer FOR loops out of habit
although DO loops are preferred. Unfortunately I can't reproduce it on
demand well enough to file a bug report.

If you take the "for" loop out of the equation, or even just move the
two "if" clauses into their own BTM and CALL it, then everything works.

Whether or not the second IF will be tested may depend on the results of
the first, it's almost like a failure on the first causes FOR loop to
start on the next iteration.

Switching to a DO loop instead of a FOR loop works around the problem,
and/or you may have better luck with IFF instead of IF.
 

samintz

Scott Mintz
May 20, 2008
1,295
11
Solon, OH, USA
#7
When writing a batch script, DO loops are far superior to FOR loops. The
debugging ease alone is worth it.

FOR loops are by definition single line statements. So even if you broke
up the statement using command grouping, that only influences the
statement visually, not programatically.

Second, CMD.EXE has many anomalies with regard to how it processes
commands vs. how TCC does it. TCC has a "emulate CMD's aberrent behavior"
mode called "Duplicate CMD.EXE Bugs."

If "Duplicate CMD.EXE Bugs" is enabled (the default), the following
command will display nothing, because the second ECHO command is discarded
along with the first when the condition fails. If Duplicate CMD.EXE Bugs
is disabled, it will display "hello":

[c:\] if 1 == 2 echo Wrong! & echo hello


The original code that was posted was:
Code:
for /A:d %i in (*.*) do (
        if exist %i\jetpdb\ (
                del /FSEXY %i\jetpdb\
        )
        if exist %i\%i.exe (
                del /F %i\%i.exe
        )
)
That simplifies down to:

for %i in (*) do (if cond1 del A & if cond2 del B)

The CMD.EXE behavior states that if cond1 is false, the 2nd IF statement
will not be executed.

-Scott

thedave <> wrote on 11/06/2009 03:59:09 PM:


> I've bumped into this many times, I still prefer FOR loops out of habit
> although DO loops are preferred. Unfortunately I can't reproduce it on
> demand well enough to file a bug report.
>
> If you take the "for" loop out of the equation, or even just move the
> two "if" clauses into their own BTM and CALL it, then everything works.
>
> Whether or not the second IF will be tested may depend on the results of
> the first, it's almost like a failure on the first causes FOR loop to
> start on the next iteration.
>
> Switching to a DO loop instead of a FOR loop works around the problem,
> and/or you may have better luck with IFF instead of IF.
>
>