Home / Microsoft / Microsoft DOS / Batch If inside For
0 Members and 1 Guest are viewing this topic. « previous next »
Pages: [1] - (Bottom) Print
Author Topic: Batch If inside For  (Read 1245 times)
Grimbear13
Topic Starter
Rookie



Posts: 43


« on: November 13, 2009, 12:38:44 PM »

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. 

I'm using this program to run through a list of .sql files and copy the ones with "PROD" found in them to another directory for review.

Thanks in advance.

for %%I in (*.sql) do (
find /n /i "PROD" %%I >> PROD_Check/PROD_Check_Lines.txt
if find "PROD" %%I (copy %%I PROD_Check)
echo 1 >> PROD_Check/i.txt
)
« Last Edit: November 13, 2009, 01:37:40 PM by Grimbear13 » IP logged
Sidewinder
Guru



Thanked: 89
Posts: 4,315

Experience: Experienced
OS: Windows XP

« Reply #1 on: November 14, 2009, 07:46:38 AM »

I think this is what you're looking for:

Code: [Select]
for %%I in (*.sql) do (
  find /n /i "PROD" %%I >> PROD_Check/PROD_Check_Lines.txt
  if errorlevel 0 (copy %%I PROD_Check)
  echo 1 >> PROD_Check/i.txt
)

I couldn't decide whether the echo statement was part of the if. Based on your code, I determined it is not.

 8)
IP logged

If you don't know where you are going, any road will get you there

                                                                            -Lewis Carroll
Grimbear13
Topic Starter
Rookie



Posts: 43


« Reply #2 on: November 16, 2009, 07:15:03 AM »

That got it to run, and it copied files, however I'm trying to copy ONLY the files that have PROD in them.  Since techincally the find never comes across an error because finding nothing is not an error (at least I don't believe it is).

And yes you were correct that echo is not in the if, it is only in the for.  Still dont know the standards for writing these yet  :).
« Last Edit: November 16, 2009, 11:42:42 AM by Grimbear13 » IP logged
Grimbear13
Topic Starter
Rookie



Posts: 43


« Reply #3 on: November 25, 2009, 10:46:42 AM »

I found an alternate way to do what I was trying to do with this, however I still have been issues with nesting If's within For loops.  Could someone post a nested If because I was told it could be my formatting, so I would like to compare.
IP logged
Salmon Trout
Prodigy



Thanked: 501
Posts: 7,365

Computer: Specs
Experience: Guru
OS: Linux variant

1
« Reply #4 on: November 25, 2009, 11:16:27 AM »

[edit] see below
« Last Edit: November 26, 2009, 02:38:20 AM by Salmon Trout » IP logged

Salmon Trout
Prodigy



Thanked: 501
Posts: 7,365

Computer: Specs
Experience: Guru
OS: Linux variant

1
« Reply #5 on: November 25, 2009, 03:49:20 PM »

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
« Last Edit: November 26, 2009, 02:40:59 AM by Salmon Trout » IP logged

Pages: [1] - (Top) Print 
Home / Microsoft / Microsoft DOS / Batch If inside For « previous next »
 


Login with username, password and session length

Old Forum Search | Forum Rules
Copyright © 2010 Computer Hope ® All rights reserved.
Powered by SMF 2.0 RC3 | SMF © 2006–2010, Simple Machines LLC
Page created in 0.109 seconds with 21 queries.