| 1. |
Solve : Batch If inside For? |
|
Answer» For some reason my PROGRAM is blowing up when I try to nest a IF within a FOR loop. I've been working in C base languages for years and am just teaching myself how to write batches so some of the syntax has been a bit weird to adjust to. Since techincally the find never comes across an error because finding nothing is not an error (at least I don't believe it is). Maybe the name "errorlevel" is misleading. Think of it as "exit code". Finding "nothing" is a result that the calling process needs to know about. Find, like most commands, always returns an errorlevel. It will be zero if the operation was successful (the string was found), and NONZERO if it was not. In command scripts ("batch files") there is a problem (or a feature if you prefer!) with variables which are both created and expanded (read) inside a parenthetical structure such as a loop or a multiline IF. This is due to the way that cmd.exe operates when interpreting a script. In a nutshell, by default cmd.exe expands all variables at runtime and plugs them in where it finds their placeholders (those sections of text with percent %signs%). Variables whose value is not yet known (those created by a set command inside a loop or if block) will have null values inside that block. If the variable in question is an implicit one such as errorlevel, it will be zero regardless of the actual return code sent by the preceding program or command. To get around this, from Windows 2000 onwards, NT scripting introduced delayed expansion. It involves two things: 1. Before the code in question, most often at the start, after the @echo off line, include this line setlocal enabledelayedexpansion 2. The relevant variables have a modified syntax - you use exclamation marks or points (!) and not percent signs (%). Now for the question of errorlevel. In MS-DOS, programs returned a code called errorlevel (or ERRORLEVEL if you like) which you could test for. Some programs or commands merely returned zero (no error) or some nonzero value (an error occurred). Others returned specific values which had meanings. It was a byte; you could have an errorlevel from 0 to 255. NT scripting post win2K uses a 16 bit word. The IF ERRORLEVEL format with no percent signs is retained in NT scripting, but it has a non-obvious catch. for nonzero errorlevels, IF ERRORLEVEL N [command] means "If the errorlevel is N or greater [command]". THUS testing for different errorlevels had to be done in descending order to work properly if errorlevel 7 [whatever] if errorlevel 6 [whatever] if errorlevel 5 [whatever] In loops, and other parenthetical structures, you should use the post-Windows 2000 %errorlevel% / !errorlevel! format. This way you can treat the errorlevel like any other variable. if %errorlevel% equ N [command] in a loop Thus: Code: [Select]setlocal enabledelayedexpansion for %%I in (*.sql) do ( find /n /i "PROD" %%I >> PROD_Check\PROD_Check_Lines.txt if !errorlevel! equ 0 (copy %%I PROD_Check) echo 1 >> PROD_Check\i.txt ) You do know that MS files/paths have reversed slashes ("\") ? if !errorlevel! equ N [command] Regarding format, these are all acceptable if condition command if condition (command) if condition ( command1 command2 [...] ) if condition (command1) else (command2) if condition ( command1 command2 [...] ) else ( command3 command4 [...] ) note that with else, the closing parenthesis of the first block, the keyword ELSE and the opening parenthesis of the second block must all be on the same line. Incidentally you can use the && and || operators to test for errorlevel. command1 && command2 command2 will execute (only) if command1 returned with an errorlevel of zero command1 || command2 command2 will execute (only) if command1 returned with an errorlevel which is nonzero. And you can do this command1 && ( command2 command3 command4 ) etc |
|