Batch errorlevel is not working properly - batch-file

so i have really problems with the ERRORLEVEL of batch. Its just not working for me.
I have a big own ms build batch script and i always get 0 back from ERRORLEVEL, whatever I do (eg. msbuild, tf get, tf checkout, copy, xcopy,...)
so i did a small example to post it here:
#echo off
set Update=1
IF %Update% == 1 (
echo.
set /p "=- Copy stuff..." <NUL
xcopy /R /Y C:\test\2.lib C:\test1
if %ERRORLEVEL% neq 0 (echo FAILED!) ELSE (echo SUCCEED!)
echo -^> done
pause
)
so its always returning succeed and printing 0 when i do: echo %ERRORLEVEL%
can you please help me with that? I really would like to use that errorlevel

you need delayed expansion here or to use IF ERRORLEVEL :
#echo off
set Update=1
IF %Update% == 1 (
echo.
set /p "=- Copy stuff..." <NUL
xcopy /R /Y C:\test\2.lib C:\test1
IF ERRORLEVEL 1 (echo FAILED!) ELSE (echo SUCCEED!)
echo -^> done
pause
)
with IF ERRORLEVEL 1 you can check if the errorlevel is 1 or bigger .

As npocmaka says, you have a delayed expansion issue.
An alternative is to ditch ERRORLEVEL and use the && and || conditional command concatenation operators instead.
#echo off
set Update=1
IF %Update% == 1 (
echo.
set /p "=- Copy stuff..." <NUL
xcopy /R /Y C:\test\2.lib C:\test1 && (echo SUCCEED!) || (echo FAILED!)
echo -^> done
pause
)
Edit showing use of multiple lines
#echo off
set Update=1
IF %Update% == 1 (
echo.
set /p "=- Copy stuff..." <NUL
xcopy /R /Y C:\test\2.lib C:\test1 && (
echo First success command
echo SUCCEED!
) || (
echo First failure command
echo FAILED!
)
echo -^> done
pause
)

Related

Log contents of text file before deleting

My script isn't logging the contents of run.txt to log.txt
I've tried to remove the delete command to see if it was deleting it too quickly and therefore couldn't log. But that wasn't the case.
What should I change?
#ECHO OFF &setlocal
SET File=run.txt
type %File%
for /f "tokens=*" %%A in (%File%) do (echo >> log.txt)
del "%File%" /s /f /q > nul
pause
Here is a very simple way to do the task you are requiring.
#echo off
REM Will only grab the first line of the file
set /p file=<run.txt
REM For the last line use a for loop
for /f "tokens=*" %%a in (%file%) do set last_line=%%a
(
echo %file%
)>>log.txt
del /f %file% >nul
If not %errorlevel% equ 0 (
ECHO ERROR - %errorlevel%
pause
exit /b
)
ECHO Success!
timeout /t 003
exit /b %errorlevel%
EXPLANATION
set /p is for set prompt. For more information you can use set /? in your CMD window or check out this site.
I wish I could speak more on what < does, but what it is doing here is piping the content of run.txt to our variable.
Then we echo out our variable to our log file with (ECHO This is our %file%)>>destination
>> is to append where > is to overwrite the file.
(
echo %file%
echo.
)>>%file%
Checking for an error is probably unnecessary, but I believe it is a good habit to build on which is what I am trying to do with that If not %errorlevel% statement.
No error? We Success and timeout ourselves for xxx seconds.
Try:
#ECHO OFF &setlocal
SET "File=run.txt"
type "%File%" >> "log.txt" && (del "%File%" /f > nul)
pause

Prompt is asking question 2 times. How can I fix this?

I tried to make a check to see if the EULA is set to true in eula.txt but when typing true it asks again and I have to type true again.
I tried on Windows 10 and using a .cmd file instead of .bat (the same thing)
#echo off
SET jarFileName=server.jar
SET jarFileUrl=https://cdn.getbukkit.org/spigot/spigot-1.12.2.jar
SET memory=4G
SET startColor=0F
SET errorColor=CF
rem Colors and things
color %startColor%
MODE CON COLS=136 LINES=36
rem Start server
:checkEULA1
if exist eula.txt (
goto checkEULA2
) else (
echo eula=false>eula.txt
goto checkEULA2
)
:checkEULA2
>nul findstr /c:"eula=true" eula.txt && (
rem EULA true
goto start
) || (
rem EULA not true
echo Do you accept the EULA? Type true if you do.
set /p eula=
echo eula=%eula% >eula.txt
goto checkEULA1
)
:start
pause
if exist %jarFileName% (
java -version >nul 2>&1|| cls&&color %errorColor%&&echo Please install Java and add it to PATH. Usually the 64 bit JDK works better. && goto exit
cls
java -Xmx%memory% -jar %jarFileName% nogui
) else (
cls
echo %jarFileName% not detected. Downloading...
powershell -Command "(New-Object Net.WebClient).DownloadFile('%jarFileurl%', '%jarFileName%')"
echo Done!
echo.
echo Press any key to start server... && pause>nul && cls && goto start
)
rem Exit
:exit
echo.
color %errorColor%
echo.
echo Press any key to exit... && pause>nul && exit
I want it to only ask the question once. No errors I can see.
I think that you could probably do this a little bit simpler:
#Echo Off
Set "startColor=0F"
Set "errorColor=CF"
Set "jarFileName=server.jar"
Set "jarFileUrl=https://cdn.getbukkit.org/spigot/spigot-1.12.2.jar"
Set "memory=4G"
FindStr /I "^eula=true$" "eula.txt" >NUL 2>&1||(Color %errorColor%
Choice /M "Do you accept the EULA"
If ErrorLevel 2 Exit /B 1
(Echo eula=true)>eula.txt)
ClS
Mode 136,36
Color %startColor%
Rem Start server
The problem is that your eula variable is only set after exiting the findstr function.
An easy solution is to create another function and goto it:
:checkEULA1
if exist eula.txt (
goto checkEULA2
) else (
echo eula=false>eula.txt
goto checkEULA2
)
:checkEULA2
findstr /c:"eula=true" "eula.txt" >nul 2>&1 && (
rem EULA true
goto start
) || (
rem EULA not true
set /p eula= Do you accept the EULA? Type true if you do:
goto setEULA
)
:setEULA
echo eula=%eula%>eula.txt
goto checkEULA1

Batch Script - Skip on errorlevel in a For loop

I am trying to have this script go to the next part if the error level of a ping to a computer does not equal 0, but I cannot get it to work. The output says the syntax is not correct. Thank you.
#echo
setlocal EnableDelayedExpansion
for /f %%a in (main.txt) do (
ping -n 1 %%a > NUL
IF %ERRORLEVEL%==0 (GOTO :COPY) ELSE GOTO :SKIP
:COPY
ROBOCOPY C:\Blah C:\Bloh
ECHO FILE COPIED
:SKIP
ECHO FILE NOT COPIED
)
You should try this:
#echo
setlocal EnableDelayedExpansion
for /f %%a in (main.txt) do (
ping -n 1 %%a >NUL
IF "!ERRORLEVEL!"=="0" (
ROBOCOPY "C:\Blah" "C:\Bloh"
ECHO FILE COPIED
) ELSE (
ECHO FILE NOT COPIED
)
)
PAUSE
There are a couple of things wrong with your code. First of all, you enable Delayed Expansion, but don't actually use it, only variables inside ! get expanded delayed. I also put quotes around your filepaths, to protect them against paths with spaces and stuff. Finally, goto and labels don't work inside for loops, so you need to replace them with if else logic
goto :Label inside a parenthesised block of code like for loops breaks the block/loop context, so the code at the label is executed as if it were outside of the block/loop. Therefore you need to work around that.
Dennis van Gils points out a way how to do it -- using if/else logic (his method as well as the following slightly modified snippet (applying numeric comparison) both require delayed expansion):
setlocal EnableDelayedExpansion
for "usebackq" /F %%A in ("main.txt") do (
> nul ping -n 1 %%A
if !ErrorLevel! EQU 0 (
robocopy "C:\Blah" "C:\Bloh"
echo FILE COPIED
) else (
echo FILE NOT COPIED
)
)
endlocal
Or like this, avoiding the necessity of delayed expansion:
for "usebackq" /F %%A in ("main.txt") do (
> nul ping -n 1 %%A
if ErrorLevel 1 (
echo FILE NOT COPIED
) else (
robocopy "C:\Blah" "C:\Bloh"
echo FILE COPIED
)
)
To check the ErrorLevel against (non-)zero, you can also use the && and || operators:
for "usebackq" /F %%A in ("main.txt") do (
> nul ping -n 1 %%A || (
echo FILE NOT COPIED
) && (
robocopy "C:\Blah" "C:\Bloh"
echo FILE COPIED
)
)
Finally, if you do want to keep the goto :Label structure, you need to use a sub-routine in order to move this part of the code outside of the () block (you also do not need delayed expansion here):
for "usebackq" /F %%A in ("main.txt") do (
> nul ping -n 1 %%A
call :SUB "C:\Blah" "C:\Bloh"
)
exit /B
:SUB
if %ErrorLevel% NEQ 0 goto :SKIP
robocopy "%~1" "%~2"
echo FILE COPIED
:SKIP
goto :EOF

How to find a certain word in a file without using ERRORLEVEL (batch)

I can use ERRORLEVEL, but tried and with a loop it failed.
I am writing a batch "shell."
Since I have tried and tried, I am finally asking for help.
The reason I don't want to use errorlevel is because the loop.
(FULL) SHELL
#set /p build=<"C:\Users\%username%\Desktop\WellOS2\WellOS\Build".txt
#title WellOS V.%build%
#echo off
goto boot
:register
cls
echo You are registering...
echo If this is an error press CTRL + C NOW...
pause
cls
set /p user= Enter your username:
set /p passwordreg= Enter your password:
mkdir "C:\Users\%username%\Desktop\WellOS2\Users\%user%"
mkdir "C:\Users\%username%\Desktop\WellOS2\Users\%user%\Documents"
echo %passwordreg% >"C:\Users\%username%\Desktop\WellOS2\Users\%user%\password".txt
echo 2 >"C:\Users\%username%\Desktop\WellOS2\OSfiles\bootset".txt
echo Your done.
pause
goto welloslog
:booterror
echo Sorry the boot file has an error. Check the user manual for BOOT$
pause
:boot
set /p boot=<"C:\Users\%username%\Desktop\WellOS2\OSfiles\bootset".txt
if %boot% == 1 goto register
if %boot% == 2 goto welloslog
goto booterror
cls
:ERROR
cls
echo ----------ERROR-------------------
echo %error%
pause
goto %back%
:welloslog
cls
echo Welcome to WellOS2!
echo ----------------LOGIN-------------
set /p user= Username:
if exist "C:\Users\%username%\Desktop\WellOS2\Users\%user%" goto pass
set error= Sorry that account doesn't exist.
set back=welloslog
goto welloslogerror
:pass
set /p password=<"C:\Users\%username%\Desktop\WellOS2\Users\%user%\password".txt
set /p passwordlog= Password:
if /i %passwordlog% == %password% goto wellos
set error= Sorry! wrong password.
set back= welloslog
goto error
:wellos
cls
:wellosnocls
echo --------------MAIN---------------
echo type help for help
set /p command= #:
if exist "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.sys" set type=sys
if exist "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.pro" set type=pro
if exist "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.sys" goto po
if exist "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.pro" goto po
set error= !Unreconized program/system program!
set back=wellos
goto error
:po
set lines=0
echo --------------%command%.%type%---------------
:porep
set /a lines=%lines% + 1
set /p "code="<"C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.%type%\%command%.%type%-%lines%".wellcode
if "%code%"=="GOWELL" goto wellosnocls
findstr /I /L "if" "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.%type%\%command%.%type%-%lines%.wellcode"
:skip
call %code%
goto porep
::Tools
:iftl
%code%
goto porep
PROGRAM OPENER (What I am talking about, and having problems with...)
:po
set lines=0
echo --------------%command%.%type%---------------
:porep
set /a lines=%lines% + 1
set /p "code="<"C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.%type%\%command%.%type%-%lines%".wellcode
if "%code%"=="GOWELL" goto wellosnocls
findstr /I /L "if" "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.%type%\%command%.%type%-%lines%.wellcode" goto iftl
:skip
call %code%
goto porep
::Tools
:iftl
%code%
goto porep
findstr "targetstring" datafilename >flagfilename
for %%a in (flagfilename) do if %%~za==0 echo not found
for %%a in (flagfilename) do if %%~za neq 0 echo found
beyond that, your question is too vague.
The following command returns all lines of a text file textfile.txt that contain the word word (remove the /I switch if you want the search to be case-sensitive):
findstr /I /L "word" "textfile.txt"
With for /F you can capture the output and test whether it is empty, as the loop does not iterate if no match is encountered:
set "FOUND="
for /F "delims=" %%F in ('
findstr /I /L "word" "textfile.txt"
') do (
set "FOUND=Yes"
)
if defined FOUND (
echo One or more matches found.
rem do something...
) else (
echo No match found.
rem do something else...
)
Type for /? and if /? in command prompt to get details about the used commands.
There is also a way to use ErrorLevel implicitly, meaning you do not have to query its value by something like %ErrorLevel%, !ErrorLevel! or if ErrorLevel, namely when using conditional command separators:
the && separator executes the following command only in case the previous one succeeded, that is, it returned an ErrorLevel of 0; (findstr returns 0 in case a match is encountered;)
the || separator executes the following command only in case the previous one failed, that is, it returned an ErrorLevel other than 0; (findstr returns a non-zero ErrorLevel in case no match is encountered;)
The following line of code demonstrates the usage:
findstr /I /L "word" "textfile.txt" && (echo One or more matches found.) || echo (No match found.)

How to write a batch file to check for specifed folders in a directory

How can I write a batch file to check for specified subfolders in a directory and then generate a log file showing the results of the findings (found it or not found). I am new to scripting and below is what I have so far:
#echo off
ECHO
SET /P QUESTION="Perform file check (Y/N)?"
if QUESTION == y goto :START_SCRIPT
:START_SCRIPT
if exist "C:\Folder\ABC" (echo found it) else echo not found;
if exist "C:\Folder\DEF" (echo found it) else echo not found;
if exist "C:\Folder\GHI" (echo found it) else echo not found;
test.bat >> out.txt
One more
#echo off
set "folder=c:\folder"
( for %%d in ("ABC" "DEF" "GHI") do if exist "%folder%\%%~d" (
echo "%%~d" found
) else (
echo "%%~d" not found
)
) >> file.log
Very simple;
#echo off
choice /m "Perform Check?"
if errorlevel 2 Exit
:loop
set /p query="Folder Name: "
if "%query%"=="" goto :end
if exist "C:\Folder\%query%" (Echo %query% Exists&Echo %query% Found >> out.txt
) Else (
Echo %query% Doesn't Exist&Echo %query% Not Found >> out.txt
)
goto :loop
:end
Echo End of Batch File&sleep 5
Exit
And that should do what you want (note it requires user input) which if is not the case, can use a log file redirected as input.
Mona
Here is how I'd do it:
#echo off
setlocal
cd /d %~dp0
call :FolderExists abc && Echo Yes || Echo No
exit /b
:FolderExists folder
for /f %%a in ('dir /b /ad') do (
if /i %%a EQU %1 exit /b 0)
exit /b 1

Resources