1

I wanted to make a basic text editor in batch and I'm using set /p to get user input and write that to a file.

When I type in something like "hello" or "hello " it works fine, but as soon as I write something with a space and another character after than, like "hello world", the window closes.

My code was:

set /p append=Write what you want to append: 

Then I tried:

set /p "append=Write what you want to append: "

which i found online, but it didn't work.

pause isn't of any help because the program crashes as soon as I press enter.

Help!

Here is the full code:

:append
set /p "append=Write what you want to append: "
if %append%==return (
    cls
    goto start
)
echo %append% >> %filename%
goto append

:override
cls
echo Name: %filename%
set /p override="Write new content: "
echo %override% > %filename%
pause
cls
goto start

:writefile
echo.
set /p filename=Write file name.extension: 
choice /c AO /m "Append to file or override? "
if %ERRORLEVEL%==1 (
    cls
    echo Name: %filename%
    goto append
) else (
    goto override
)
Nihil
  • 37
  • 1
  • 8
  • To debug a batch file, remove `echo off` if present in batch file or change it to `echo on` or comment out `echo off`, open a command prompt window, type the batch file name with file extension and full path enclosed in double quotes, and run the batch file. Now it can be seen which command lines are executed after preprocessing and where the batch file is exited in case of an error. Double clicking on a batch file is not good for testing a batch file as command process is always automatically closed and therefore error messages can't be seen. – Mofi Nov 26 '16 at 17:32
  • I tried opening the file from the command prompt, if I write "hello world" (without quotes) it says it doesn't expect "world" – Nihil Nov 26 '16 at 17:36
  • @Mofi Oh the joys of a broken command processor! "Principle of least surprise", anyone? – ClickRick Nov 26 '16 at 17:38
  • You are getting that error because you are not protecting your string comparisons. – Squashman Nov 26 '16 at 19:05

3 Answers3

2

Whenever the user of a batch file is prompted for a string using set /P the user has the freedom to

  1. enter nothing at all by pressing simply just RETURN or ENTER which results in the environment variable is still not defined after prompt if it was not defined before, or the variable keeps its current value if it was already defined before, or
  2. enter really anything including a string which could result in an exit of batch execution because of a syntax error somewhere in batch code later or an unwanted behavior.

Let us look on the line

if %append%==return (

If environment variable is not defined before with a default value and the batch user enters nothing, this line expands during preprocessing step to:

if ==return (

This command line is of course invalid and results in an exit of batch processing because of a syntax error.

Now let us assume the user enters the string:

I want to append this string.

Then the IF command line expands to:

if I want to append this string.==return (

And of course also this command line is invalid.

The other answerers suggested to enclose the two strings to compare in double quotes, i.e. use the command line:

if "%append%"=="return" (

But does that really solve all possible issues?

Is the code now really safe against any user input.

Let us look what happens if the user enters the string:

" is a double quote. It should be used around paths like "%ProgramFiles(x86)%".

The IF command line expands now to:

if "" is a double quote. It should be used around paths like "%ProgramFiles(x86)%""=="return" (

And this command line is again invalid and results in an exit of the batch file because of a syntax error.

So how to make batch code safe against really any user input?

The solution is using delayed environment variable expansion wherever the user entered string is referenced.

Example:

@echo off
setlocal EnableDelayedExpansion
echo.
echo Enter EXIT to exit this batch script.

:PromptUser
echo.
set "UserInput=Nothing^!"
set /P "UserInput=Please enter a string: "
if /I "!UserInput!" == "exit" goto EndBatch
echo You entered: !UserInput!
goto PromptUser

:EndBatch
echo.
echo Thanks for running this example batch code.
echo.
echo The batch file ends in 3 seconds ...
endlocal
%SystemRoot%\System32\ping.exe localhost -n 4 >nul

By using delayed expansion the user entered string can't result in a invalid or unexpected command line in later code. This is also important for the command line

echo !append!>>%filename%

It is important to have no space character left of >> or this space character is also written into the file as trailing space.

But delayed expansion is also important here in case of user enters for example just 2 which would result with echo %append%>>%filename% in

echo 2>>%filename%

which does not append the character 2 to the file, but would append STDERR to the file which results in an empty line written to the file.

Delayed expansion is also needed for this string entered by the user:

(Var1 > 0x2F) && (Var1 < 0x3A)

which should be written with ECHO into the file as entered and not what Windows command interpreter would produce after expanding the string when using echo %append%>>%filename%.

Mofi
  • 46,139
  • 17
  • 80
  • 143
1

Change your set to put quotes in the right place around the prompt string, and your if line to put quotes around the string being tested.

set /p append="Write what you want: " 
set append 
echo xx%append%yy
if "%append%"=="return" (
   echo Yes!
)
ClickRick
  • 1,553
  • 2
  • 17
  • 37
1

Your problem is with

if %append%==return (

which will give a syntax error if append contains spaces.

use

if "%append%"=="return" (

"quoting a string" makes cmd interpret it as a single element so the required syntax of if,

if string==string (

is no longer violated.

Magoo
  • 77,302
  • 8
  • 62
  • 84