Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set errorlevel in Windows batch file

Tags:

batch-file

I am writing a batch script that will loop through each line of a text file, (each line containing a filename) check if the file exists and then runs the file and moves it.

Here is my batch script:

REM Loop through each line of input.txt
FOR /F "tokens=1-3 delims=, " %%i IN (./ready/input.txt) DO (
  ECHO.
  ECHO.
  ECHO.
  ECHO Check %%i exists, set error flag if it doesnt
  if not exist .\ready\%%i set errorlevel=2
echo return code is %errorlevel%

  ECHO Run %%i if it exists
  if errorlevel 0 call .\ready\%%i

  ECHO Move %%i to archive if no error occured 
  if errorlevel 0 copy .\ready\%%i .\archive\%mydate%_%mytime%_%%j_%%k_%%i

  ECHO Copy line of text to the new output.txt file if an error occured
  if %errorlevel% NEQ 0 >>output.txt %%i, %%j, %%k
)

Here is the output: enter image description here

I do not understand why the "if errorlevel" is not working as expected... if the file does not exist (as in this example where it does not exist) it should NOT try to run the file, it should NOT copy the file, and it should echo a 2 not a 0

Edit 1: I was reading another SO Post regarding "delayed environment variable expansion" I am not sure if this issue is related

like image 694
Kairan Avatar asked Jan 02 '14 22:01

Kairan


People also ask

What is Errorlevel in batch file?

Error Level. The environmental variable %ERRORLEVEL% contains the return code of the last executed program or script.

What does errorlevel 1 mean?

In Microsoft Windows and MS-DOS, an errorlevel is the integer number returned by a child process when it terminates. Errorlevel is 0 if the process was successful. Errorlevel is 1 or greater if the process encountered an error.

What is error level CMD?

The ERRORLEVEL is a value returned by most cmd.exe commands when they end that change depending on a series of conditions, so knowing the value that the commands return is valuable information that may aid to write better Batch files.

What is GEQ in batch file?

GEQ is a 'Greater Than or Equal To' comparison operator for the IF command. Example. C:\> If 25 GEQ 50 ECHO smaller. C:\> If "5" GEQ "444" ECHO smaller.


2 Answers

ERRORLEVEL and %ERRORLEVEL% are two different variables. That means your code with echo return code is %errorlevel% and if %errorlevel% NEQ 0 >>output.txt %%i, %%j, %%k is probably wrong.

ERRORLEVEL is builtin and used to fetch the result of the last command. You can use it like:

IF ERRORLEVEL 1 ECHO error level is 1 or more

ERRORLEVEL cannot be set, just like bash does not let you set ?= ...

%ERRORLEVEL% is an environmental variable. If %ERRORLEVEL% is set, then its used in your script when you use %ERRORLEVEL%. If %ERRORLEVEL% is not set AND if command extensions are enabled, then it falls back to ERRORLEVEL. ERRORLEVEL does not update %ERRORLEVEL%.

Raymond Chen has a good blog entry on it: ERRORLEVEL is not %ERRORLEVEL%. Some of the content in this answer was shamelessly lifted from it.

like image 175
jww Avatar answered Oct 08 '22 07:10

jww


@ECHO OFF
SETLOCAL
DEL output.txt 2>nul
REM Loop through each line of input.txt
FOR /F "tokens=1-3 delims=, " %%i IN (.\ready\input.txt) DO (
  ECHO.
  ECHO.
  ECHO.
  ECHO Check %%i exists, set error flag if it doesnt
  if exist .\ready\%%i (set "errorflag=") ELSE (set errorflag=2)
CALL echo return code is %%errorflag%%

  ECHO Run %%i if it exists
  if NOT DEFINED errorflag (
   call .\ready\%%i
   ECHO Move %%i to archive if no error occured
   if errorlevel 1 (SET errorflag=3) ELSE (ECHO copy .\ready\%%i .\archive\%mydate%_%mytime%_%%j_%%k_%%i)
  )
  ECHO Copy line of text to the new output.txt file if an error occured
  if DEFINED errorflag >>output.txt ECHO %%i, %%j, %%k
)
GOTO :EOF

Here's a rewritten procedure.

Note: output.txt is deleted at the start, else the >> would append to any existing file. 2>nul suppresses error messages if the delete fails (eg. file not exist)

Within a block statement (a parenthesised series of statements), the ENTIRE block is parsed and THEN executed. Any %var% within the block will be replaced by that variable's value AT THE TIME THE BLOCK IS PARSED - before the block is executed.

Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.

Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the chnaged value of var or 2) to call a subroutine to perform further processing using the changed values.

Note therefore the use of CALL ECHO %%var%% which displays the changed value of var. CALL ECHO %%errorlevel%% displays, but sadly then RESETS errorlevel.

IF DEFINED var is true if var is CURRENTLY defined.

ERRORLEVEL is a special varable name. It is set by the system, but if set by the user, the user-assigned value overrides the system value.

IF ERRORLEVEL n is TRUE if errorlevel is n OR GREATER THAN n. IF ERRORLEVEL 0 is therefore always true.

The syntax SET "var=value" (where value may be empty) is used to ensure that any stray spaces at the end of a line are NOT included in the value assigned.

The required commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO COPY to COPY to actually copy the files.

I used the following input.txt:

seterr1.bat, J1, K1
seterr5.bat,J2,K2
seterr0.bat,J3 K3
seterr5.bat, J4, K4
notexist.bat, J5, K5

With existing files seterr*.bat which contain

@ECHO OFF
EXIT /b 1

(where the 1 in the last line determines the errorlevel returned)

and received the resultant output:

Check seterr1.bat exists, set error flag if it doesnt
return code is 
Run seterr1.bat if it exists
Move seterr1.bat to archive if no error occured
Copy line of text to the new output.txt file if an error occured

Check seterr5.bat exists, set error flag if it doesnt
return code is 
Run seterr5.bat if it exists
Move seterr5.bat to archive if no error occured
Copy line of text to the new output.txt file if an error occured

Check seterr0.bat exists, set error flag if it doesnt
return code is 
Run seterr0.bat if it exists
Move seterr0.bat to archive if no error occured
copy .\ready\seterr0.bat .\archive\__J3_K3_seterr0.bat
Copy line of text to the new output.txt file if an error occured

Check seterr5.bat exists, set error flag if it doesnt
return code is 
Run seterr5.bat if it exists
Move seterr5.bat to archive if no error occured
Copy line of text to the new output.txt file if an error occured

Check notexist.bat exists, set error flag if it doesnt
return code is 2
Run notexist.bat if it exists
Copy line of text to the new output.txt file if an error occured

Note that the COPY is merely ECHOed as I mentioned earlier.

and output.txt

seterr1.bat, J1, K1
seterr5.bat, J2, K2
seterr5.bat, J4, K4
notexist.bat, J5, K5
like image 30
Magoo Avatar answered Oct 08 '22 07:10

Magoo