Search code examples
batch-file

If Statement Echoing Out Even Though @echo off and With >nul and2>nul


I am very inexperienced with batch, and therefore I am reliant on chatGPT to figure out some syntax, but it seems that chatGPT cannot solve the problem I'm having.

As I am attempting to follow a textbook on C++, there are example programs. I wish to run these programs, but I constantly need to compile. Visual Studio doesn't provide an easy way to compile a program on a whim like you might with Eclipse and a Java file (I cannot simply create a new file and then run that said file because Visual Studio 2022 is expecting a single main function out of all .cpp files in the project, meaning I have to constantly use cl /EHsc in the command prompt). I have therefore attempted to create a batch script to compile programs for me using Visual Studio's compiler.

What I have created thus far is this:

@echo off

:: Set up the Visual Studio environment
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64

:: Prompt for the source directory
:askSourceDirAgain
set /p source_dir="Enter source directory: "
if not exist %source_dir% (
    echo Directory not found, please try again.
    goto askSourceDirAgain
)
echo Source directory found

:askSourceFileAgain
set /p "source_file=Enter cpp file name: "

:: append .cpp if not provided
echo %source_file% | findstr /i "\.cpp$" >nul
if errorlevel 1 (
    set "source_file=%source_file%.cpp"
)
pause

:: verify file exists
if not exist "%source_dir%\%source_file%" 1>nul 2>nul  (
    echo File %source_file% not found in directory, please try again.
    goto askSourceFileAgain
)

:: compile the program
:recompileProgram
set output_dir="%source_dir%\Compiled"
if not exist "%output_dir%" mkdir "%output_dir%\Compiled"
cl /EHsc "%source_dir%\%source_file%" /Fe"%output_dir%\%~n0.exe"

:: ask to run the compiled program
set /p runProgram="Run the compiled program? (y/n)"
if /i "%runProgram%"=="y" (
    start cmd /k "%output_dir%\%~n1.exe"
)

:: ask the user if they want to recompile, change directory, or exit
:chooseNextStep
echo "Choose an the next option"
echo "1. Recompile"
echo "2. Choose another program to compile"
echo "3. Choose another directory and compile another program"
echo "4. Exit"
set /p choice="Choice: "

if "%choice%"=="1" (
    goto recompileProgram
) else if "%choice%"=="2" (
    goto askSourceFileAgain
) else if "%choice%"=="3" (
    goto askSourceDirAgain
) else if "%choice%"=="4" (
    exit /b 0
) else (
    echo "Invalid response, please try again."
    goto chooseNextStep
)

The problem I'm having is that if not exist "%source_dir%\%source_file%" 1>nul 2>nul is printing out text when it should not be, even though (as far as I understand) I am sending outputs to a nul and echo is off.

The output I receive, when purposely providing a file name that does not exist, in the terminal is:

Enter cpp file name: wdaw
Press any key to continue . . .
'--' is not recognized as an internal or external command,
operable program or batch file.
File wdaw.cpp not found in directory, please try again.
Enter cpp file name:

When the output I expect is:

Enter cpp file name: wdaw
Press any key to continue . . .
File wdaw.cpp not found in directory, please try again.
Enter cpp file name:

The pause is in there for debugging.

I'm very confident there are other problems in this script, since like I said I am rather inexperienced in batch and I am trying to utilize chatGPT, so feel free to point those out as well.


Solution

  • Not sure where the -- is coming from but your regular expression will never match because echo has a nasty habit of including spaces up until the first (in your case) redirection character. So

    echo %source_file% | something
    

    will output the source file followed by a space.

    You should instead use:

    echo %source_file%| something
    

    In terms of finding out where the problem lies, comment out the echo off so that you can see exactly what line is running when the error occurs. In other words, put up with the annoying output until you have debugged the code.


    Oh, and just a few side notes.

    First, be very careful with using :: as a comment marker. This actually suborns the label mechanism and doesn't work in all cases you may expect it to (for example inside multi-line if statements). You would be better off just using rem, it's only one extra character and is the canonical way to do comments.

    Second, the 1>nul 2>nul applies to the entire command, including the stuff inside ( ... ). In particular, you'll never see the output of the echo since it's being sent to the bit-bucket.

    Something like this shoud fix that issue:

    if exist "%source_dir%\%source_file%" 1>nul 2>nul goto :found_it
    echo File %source_file% not found in directory, please try again.
    goto askSourceFileAgain
    :found_it