Conditional execution (IF, ELSE) NOT WORKING - batch-file

I want to write a batch script statement where:
FINDSTR has to check for a string AND IF found then just print out FAILED and end the program
IF NOT FOUND then go check/look for another string AND IF FOUND then print out SUCCEEDED and close the program, IF NOT FOUND then print out the error message again.
Any ideas?
Here is what I did:
ECHO Checking the log file for errors...
FINDSTR /C:"Open failed" some_Log.txt && (ECHO Deployment FAILED.
cscript //nologo success_mail.vbs
pause) || FINDSTR "RC (return code) = 0" && (ECHO Deployment was successful.
cscript //nologo fail_mail.vbs
pause)
I don't know why it is not working. Any help would be appreciated.
Here is what i my latest one looks like:
ECHO Checking the log file for errors...
FINDSTR /C:"Open failed" some_Log.txt some_Log.txt && (
ECHO Deployment FAILED.
cscript //nologo fail_mail.vbs
GOTO offshore ) || (
FINDSTR /C:"RC (return code) = 0" some_Log.txt && (
ECHO Deployment was successful.
cscript //nologo success_mail.vbs
GOTO offshore)
)
And, it is not working. Do you see any errors? Thanks in advance.

I see a couple of potential problems.
Your %workDir% or %filenm% could contain spaces or special characters. To be safe you should enclose them in quotes if you haven't already done so in the values.
You must be careful when using both && and || operators. If the command(s) after the && fail, then it can cause the script to fall into the || section, even though the original command before the && succeeded. I'm worried about your CSCRIPT command to send mail. Even if it succeeds today, perhaps it could fail in the future and your logic could be impacted.
I'm guessing that the 2nd search string is supposed to be a phrase and not 5 different searches. Remember that search strings are delimited by space unless the /C option is used.
Your 2nd FINDSTR is hanging because you have neglected to provide a file as input, so it is waiting for data on stdin.
I would structure your code like so
ECHO Checking the log file for errors...
set "file=%workDir%\%filenm%_DEV_Log.txt"
set "search1=Error: Open failed because: No such file or directory"
set "search2=RC (return code) = 0"
set "err="
FINDSTR /C:"%search1%" "%file%" && (set err=1) || (
FINDSTR /C:"%search2%" "%file%" || set err=1
)
if defined err (
ECHO Deployment FAILED.
cscript //nologo success_mail.vbs "%filenm%_ddl_DEV.sql" "%file%"
pause
) else (
ECHO Deployment was successful.
cscript //nologo fail_mail.vbs "%filenm%_ddl_DEV.sql" "%file%"
pause
)

Related

String Assertion/Throwing Exception in Batch Files

bat file via Jenkins. I have a part of code which looks as below
IF %Status% == Completed (
Echo Process has executed successfully
)
ELSE (
<Code to be added>
)
My requirement is that if Status has a value other than 'Completed' then the bat file must throw an exception or something so that the Jenkins Build Fails. Is there any way of assertions or throwing exceptions in bat files? Please help me with this?
Each line of a batch file is seen as a new command. Else on its own is not, so as it is on a new line, it is seen as one. You need to put the parenthesis on the same line as else.
Additionally, you need to double quote your matches to ensure you eliminate any possible whitespace. I have added /i switch to the if statement to make the match case insensitive.
IF /i "%Status%" == "Completed" (
echo Process has executed successfully
) else (
echo Failed to build
pause
exit /b 1
)
A different way is to not use else.
IF not /i "%Status%" == "Completed" goto :error
echo Process has executed successfully
echo other success code goes here
goto :eof
:error
echo Your code has failed.
pause
goto :eof

Why batch sometimes does not process commands like CMD does and gives unexpected and different results [duplicate]

This question already has an answer here:
wrong value of %errorlevel% in nested if in .bat file
(1 answer)
Closed 2 years ago.
When I run a command from the CMD directly it works perfectly fine but when run the same command in a batch file (or Jenkins using batch) it gives me a different result and I dont understand why.
To explain it simple, I'm running command below to search for a literal string within a log file:
findstr /C:"MY STRING WITH A %variable%" M:\Logs\output.log
If I check the %ERRORLEVEL% of the result it shows the expected values (0 = found the string or 1 = didnt find it)
However, when I run the same line from a batch file, even from Jenkins, the result is always 0, even though the string is not present in the log, the %ERRORLEVEL% is always 0.
This is the portion of the batch file which includes the command:
if %COUNTER% ==1 (
if not exist M:\Logs\current_bak (
ROBOCOPY "M:\Logs\tkcurrent" "M:\Logs\tkcurrent_bak"
REN "M:\Logs\current" "M:\Logs\current_bak"
MKDIR M:\Logs\current
echo Folders have been backed up
) else (
echo Back up folders are already in place )
findstr /C:"MY STRING WITH A %variable%" M:\Logs\output.log
if %ERRORLEVEL% == 0 (
echo Process has already being kicked off for the files with date %YYMMDD%, skipping it...
echo Download and backup compleated
exit /b 0 )
else (
echo Triggering next Jenkins Job:
curl -I http://<user>:<token>#remoteserver.domain.com:<port>/job/Hello_World/build?token=hello_world
exit /b 0 )
)
Has someone experienced this in the past or can guide me better on what I'm doing wrong or not understanding?
Thanks a lot!
Your error is a basic syntactical error that I've made plenty of times as well :P. The issue is in your else statement which is a peculiar issue, but what happens is that the else only will get processed if it is on the same line as the if statement.
PROOF OF CONCEPT
If I have the if statement and else on different lines like so:
#echo off
echo test
if errorlevel 1 (echo here)
else (echo not there)
pause
This will have the error:
'else' is not recognized as an internal or external command,
operable program or batch file.
However if I change the code a tiny bit so that the else is on the same line as the if, like so:
#echo off
echo test
if errorlevel 1 (echo here
) else (echo not there)
pause
It will not have an error and output
test
not there
Your code done correctly would be:
if %COUNTER%==1 (
if not exist M:\Logs\current_bak (
ROBOCOPY "M:\Logs\tkcurrent" "M:\Logs\tkcurrent_bak"
REN "M:\Logs\current" "M:\Logs\current_bak"
MKDIR M:\Logs\current
echo Folders have been backed up
) else (
echo Back up folders are already in place )
findstr /C:"MY STRING WITH A %variable%" M:\Logs\output.log
if %ERRORLEVEL% == 0 (
echo Process has already being kicked off for the files with date %YYMMDD%, skipping it...
echo Download and backup compleated
exit /b 0
) else (
echo Triggering next Jenkins Job:
curl -I http://<user>:<token>#remoteserver.domain.com:<port>/job/Hello_World/build?token=hello_world
exit /b 0 )
)
For more information on this type in if /? into cmd.
Note: I also fixed I believe a typo in your code of findsrt instead of findstr

How to search a text file in batch for a specific symbol and alter the script depending on the result

I need to create a command that allows me to insert a check of a text file for a very specific symbol (’) and I am having trouble. It is a single quotation mark and it occasionally is found on some folders that need to be zipped and when my batch zipper encounters the folder with the symbol in it's name, it just starts having a lot of problems and creates weird files. I am not going into a lot of detail, but I just need a way to (in plain terms) check if a text file contains the symbol (’) and if it does, send the script to an error line (just something to indicate the symbol was found, like "echo error found"). And if not, then just send it to the rest of the script...
Like FINDSTR "’" dirlist.txt
if found goto err else goto resume
I know that is very incorrect but you get the idea.
Here is what I have so far and I still have made no progress getting it to work:
findstr /i /c:"’" C:\ACFZ\FORZIP\dirlist.txt >2
if %errorlevel% EQU 0 (goto LABEL0) else (goto LABEL1)
:LABEL0
msg %username& "An invalid symbol has been found. Remove any single quotation marks (’) from the folder names and try again. If unsure, simply remove anything that looks like an apostrophe."
pause
goto ERROR
:LABEL1
echo No errors found, continuing
pause
goto ZIPSTART
:ERROR
echo an error was found, exiting...
pause
goto EXIT
It always ends up saying no errors, even though the file has the symbol in it.
Here is the text file I need to search (dirlist)
2082708 Amboy Bank
2082712 Cavender’s
2082736 Elizabeth Board of Education
2082763 Tri-Valley Developmental Services LLC
2082773 Vector Management
OK, so I finally got it working right... Thanks to Harvey, I used the method of outputting any results to a separate file, and then checking that file for contents. Which actually works great, because if it finds an issue, it will show you the full name of the problem folder(s) so you can easily fix it.
Here is the snippet of the working part:
findstr "'" C:\ACFZ\FORZIP\dirlist.txt > error.txt
findstr "." error.txt >nul
IF %ERRORLEVEL% EQU 0 GOTO POPUP
IF %ERRORLEVEL% EQU 1 GOTO ALLCLEAR
and here it is with a bit more detail:
CD C:\ACFZ\FORZIP
DIR /AD /B /ON >dirlist.txt
Echo Checking for errors in folder names...
ping -n 3 localhost >nul
REM that is not an apostrophe!
findstr "'" C:\ACFZ\FORZIP\dirlist.txt > error.txt
findstr "." error.txt >nul
IF %ERRORLEVEL% EQU 0 GOTO POPUP
IF %ERRORLEVEL% EQU 1 GOTO ALLCLEAR
REM Errorlevel 0= Something found, 1= nothing found
:POPUP
color cf
msg %username% "An invalid symbol has been found. Remove any single quotation marks (’) from the folder names and try again. If unsure, simply remove anything that looks like an apostrophe."
goto ERROR
:ALLCLEAR
echo No errors found, continuing...
ping -n 3 localhost >nul
ping -n 3 localhost >nul
goto ZIPSTART
:ERROR
echo An error was found in the following folder name(s) below:^
findstr "." error.txt
echo.
Echo Remove any symbols from the above folder name(s)
echo within your completed folder and try again.
Echo This program will now exit.
pause
goto EXIT
:ZIPSTART
REM Zip contents of each directory
for /f "tokens=*" %%a in (dirlist.txt) do (
CD "%%a"
wzzip "C:\ACFZ\ZIPPED\%%a.zip"
CD..
)
Glad I was able to fix this. I guess WinZip goes really crazy from that quotation mark. The reason I needed this was I wrote this batch script (there is more to it than what I have above, as this was the part I needed to work on) to automate the zipping and backup process at my work, so that the folders for the month's jobs are zipped up and then copied onto the server for archive. It was a pain to manually do it, so with this I can just do it all in one step.
Oh and yeah the errorlevel issue was I did not have it entered correctly. I did not space them over to the right.
Thanks to all who helped.
%error_level% indicates the status of the execution which always successful (0) unless you pass in wrong arguments (e.g. try run findstr without argument or with a wrong file name).
In your case, you need to examine the output (messages printed on the screen) of findstr. One approach is to rely on the fact that nothing is printed on the screen if findstr finds no string matched the search. For example:
set found=""
findstr "'" C:\ACFZ\FORZIP\dirlist.txt > findresult.txt
call:CheckEmptyFile findresult.txt found
if "%found%" EQU "FOUND" (
echo An invalid symbol has been found
) else (
echo No errors found, continuing
)
REM your execution goes here
REM Clean up
del findresult.txt
goto :eof
:CheckEmptyFile
if %~z1 == 0 (
set "%~2=NOTFOUND"
) else (
set "%~2=FOUND"
)
goto :eof
(Reference: Windows BAT : test if a specific file is empty)

Batch script that monitors for file changes

I need to create a batch script that continually monitors a specific file for changes, in this case, LogTest.txt.
When the file is updated it will trigger a VBScript message box, which displays the last line from within LogTest.txt. The idea is that this will continue monitoring after the message box is cleared.
I have tried using the forfiles option, but this really only lets me deal with the date and not the time. I know that PowerShell and other options are available, but for reasons that are just too long to explain I am limited to being only able to use a batch and VBScript.
Batch File:
#echo off
:RENEW
forfiles /m LogTest.txt /d 0
if %errorlevel% == 0 (
echo The file was modified today
forfiles /M LogTest.txt /C "cmd /c echo #file #fdate #ftime"
cscript MessageBox.vbs "Error found."
REM do whatever else you need to do
) else (
echo The file has not been modified today
dir /T:W LogTest.txt
REM do whatever else you need to do
)
goto :RENEW
MessageBox.vbs:
Set objArgs = WScript.Arguments
messageText = objArgs(0)
MsgBox "This is an error", vbOkCancel + vbExclamation, "Error Found"
There is an archive attribute on every file. Windows sets this attribute on every write access to the file.
You can set it with the attrib command and check it for example with:
#echo off
:loop
timeout -t 1 >nul
for %%i in (LogTest.txt) do echo %%~ai|find "a">nul || goto :loop
echo file was changed
rem do workload
attrib -a LogTest.txt
goto :loop
timeout /t 1 >nul: small wait interval to reduce CPU-Load (never build a loop without some idle time)
for %%i in (logTest.txt) do... process the file
echo %%~ai print the attributes (see for /? for details)
|find "a" >nul try to find the "a"rchive-attribute in the output of the previous echo and redirect any output to nirvana (we don't need it, just the errorlevel)
|| goto :loop works as "if previous command (find) failed, then start again at the label :loop"
If find was successful (there is the archive attribute), then the next lines will be processed (echo file was changed...)
attrib -a LogTest.txt unsets the archive attribute of the file.

IF EXIST - Files Without an Extension

A working script that moves various files based on file name runs successfully. After the script is done it will check two directories for any lingering files using IF EXIST *.txt. This works great except I've noticed some files with no extension. These were not an issue before and since that cannot be helped due to processes out of my control, I need to amend my script.
My only idea is the following code. Bear with as there are two conditions:
:check1
PUSHD "\\UNC\path1" &&(
DIR /A-D *.
IF %errorlevel% NEQ 0 GOTO check2
) & POPD
:add1
ECHO Add note to the log file
:check2
PUSHD "\\UNC\path2" &&(
DIR /A-D *.
IF %errorlevel% NEQ 0 GOTO laststep
) & POPD
:add2
ECHO Add note to the log file
:laststep
Some other code before exiting
This should run DIR on the path and if files without extensions exist, it will have %errorlevel% zero and move on to the next check. If there are no files present, it will have %errorlevel% not zero (likely 1) and it will append some text to the log before the next check. Check two will do the same.
This seems to be awfully complicated and I am not able to find a "one-liner" solution that is as easy as IF EXIST. I realize I can use *. but that returns directories as well and may result in an incorrect %errorlevel%.
Updated Code
Where I normally set my variables, I also SET the two paths to run DIR against. This way they can be used more easily elsewhere and I bypass the UNC Path error I normally get - reasons for that are unknown to me. The updated file check, used only for files without an extension, is:
DIR %p1% /b /a-d|FIND /v "." && ECHO Found 1 >> %log%
DIR %p2% /b /a-d|FIND /v "." && ECHO Found 2 >> %log%
FINDSTR /I "Found" %log%
IF %errorlevel% EQU 0 GOTO stillthere
:nofiles
Some code
GOTO domore
:stillthere
Some code
:domore
Other code before exit
Thank you for the responses, I've learned from this.
Is this what you want to find?
dir /b /a-d |find /v "."
#ECHO OFF
SETLOCAL
:check1
PUSHD "u:\path1"
DIR /A-D *. >NUL 2>NUL
IF %errorlevel% EQU 0 ECHO Add note \path1 to the log file
POPD
PUSHD "u:\path2"
DIR /A-D *. >NUL 2>NUL
IF %errorlevel% EQU 0 ECHO Add note \path2 to the log file
POPD
:laststep
:: Some other code before exiting
GOTO :EOF
Your problems include:
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 - the same thing applies to a FOR ... DO (block).
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
and you are potentially jumping out of a PUSHD/POPD bracket which would mean your POPD won't necessarily restore your starting directory.
(Note that I used u:\ rather than a server to suit my system)
You are already using && to verify PUSHD worked. You can do the same with your DIR /-D. I find it makes life easier. Also, you probably want to hide any error message if *. is not found, especially since that is the expected condition. I also hid the display of any files that might be found, but you can certainly get rid of that redirection. You might also want to hide error message if PUSHD fails, but I didn't implement that.
PUSHD "\\UNC\path1" && (
DIR /A-D *. 1>nul 2>nul && ECHO Add note to the log file
POPD
)
PUSHD "\\UNC\path2" && (
DIR /A-D *. 1>nul 2>nul && ECHO Add note to the log file
POPD
)
ECHO Some other code before exiting

Resources