4

I have a problem with GOTO command and affiliated labels.

Facts: Given a bunch of files from a folder (they are log errors) I need to open them and check if they contain a specific string. If yes then eliminate some characters (all the chars after the last appearance of "_", including itself) from the file names and do other operations.

For cutting off the chars I'm using GOTO command in a loop manner as I found it described here: http://www.robvanderwoude.com/battech_while_loops.php

The script is:

@echo off
setlocal EnableDelayedExpansion

cls

for %%X in (D:\e-pub\outbox\logs\*.*) do (

    for /F "tokens=7" %%S in (%%X) do (

        if /i "%%S"=="<ml>" (
            SET fisier=%%~nX
            SET cond=!fisier:~-1!
            SET fisier=!fisier:~0,-1!

            :loopStart
            rem condition to break the loop
            if !cond!==_ goto loopEnd
            SET cond=!fisier:~-1!
            SET fisier=!fisier:~0,-1!
            goto loopStart

            :loopEnd

            rem here it should be out of a loop
            rem other stuff to do with var !fisier!
            rem the following line is not executed because of the label loopEnd
            echo !fisier!
        )
    )
) 

pause

The script is not running because there is an empty line after the label loopEnd?! If I'm writing any instructions right after that label they will be executed but the rest of iterations from the first for statement won't be executed (the log errors folder contains more one file)

Can someone provide help?

Ergil
  • 41
  • 1
  • 2
  • show a sample of your log file with the string to find, and what things you need removed. Show the final output of what you want. – ghostdog74 Oct 20 '10 at 14:09
  • From my point of view it's not relevant the content but the way of doing it – Ergil Oct 25 '10 at 08:21

2 Answers2

12

You've got two problems.

One problem is that a goto breaks a for-loop. The other, labels are quite difficult in parenthesis.

The goto breaks always and all nested loops, even if the label of the goto is in the same block, and the for-variables are lost immediately after the jump.

In parenthesis lables are "two line" oriented! I experimented with labels and here are some results for parenthesis.

When a label occurs, the next line has to be in the correct format for a "secondary" line.

That's why this fails.

(
:this label fails with a syntax error
)

(
:this works
:because this line is a "legal" secondary line
)

(
:: The remark style
:: fails, because it's not "legal" to use a double colon, because it's not a legal path (in the most cases)
)

(
:and now I got courious & echo This will not echo'd
:but & echo You can see this !
)

For the second line some steps of the batch parser are skipped.

@ doesn't work, @echo Hello tries to start a file named @echo.bat.

Splitting of parenthesis fails, like in echo( hello.
Labels are handeled as a file name, :echo checks only if :echo is a valid file name and then skip this part.

::hello searches on the drive ::.
For test purposes the drive :: can be created with subst :: c:\temp.
As labels are simply ignored on the second line, ampersands and also pipes work, but the file on :: have to exist.

(
echo @echo This is %~f0
) > %TEMP%\testLabel.bat

REM create Drive ::
subst :: %temp% 
(
:Label 
::\testLabel.bat The bat will not be executed | echo But this
)
subst /D ::
jeb
  • 70,992
  • 15
  • 159
  • 202
  • One thing. On the second example you've introduced a second label. In the terms of cmd.exe wouldn't the second label require another "legal line"? Tnx for explanations. – Ergil Oct 25 '10 at 08:26
  • No, if a label is in the "secondary line", it does not require another "secondary line". The sec-line is parsed different than the rest, as you can see in the last example – jeb Oct 25 '10 at 15:08
  • Thank you for the answer and your time – Ergil Oct 25 '10 at 20:15
  • 3
    I just want to amend that: 1. indention does not at all affect the behaviour; 2. in the last example the result is the same when you replace the pipe `|` by an `&` (so the result is definitely not caused by the new `cmd` instances initialised by the pipe)... – aschipfl Dec 24 '16 at 14:11
2

Comments / Remarks

:: This is a REMark

A colon (:), which is actually the LABEL tag, can be used for comments instead of REM, by doubling it (::), except within parentheses (i.e. except within a FOR loop).

Using a double-label within a loop can cause the batch script to fail, but ONLY if:

  • The double-label is followed by a second double-label on the next line
  • The double-label is followed by an empty line on the next line
  • The double-label is the last line in the loop

In other words: if used within a loop, the double-label must be followed by a line which contains normal (i.e. valid) syntax. Even a single-label is valid syntax.

This error never occurs if the double-label is replaced with REM.

The error arising from a double-label occurs because CMD.EXE interprets :: as a drive letter (like C:).

.

Note - This is an explanation for one of the problems mentioned in Jeb's answer, a point which he raises but doesn't deal with.

Ed999
  • 1,867
  • 1
  • 14
  • 13