1

I am making a operating system in batch. I have a problem with the input system. If I enter a space (or multiple spaces) as an input, it shows an error that shouldn't be there. And I don't know how to fix it.

P.S. The line with if "%comm%"=="" goto loop checks if the output is blank. And this is not the error maker.

@echo off
color a
:loop
set comm=
title %username%@%computername% : %cd% 
set /p comm=[%username%@%computername%]
if "%comm%"=="" goto loop

if exist "%cd%"\%comm%.* (
call "%cd%"\%comm% 2>nul
)

goto error
:error
echo '%comm%' is not recognized as a programm or command.
goto loop
:nosw
@echo off
cls
echo Access Denied.
pause
2
  • is %comm% allowed to have spaces?
    – Stephan
    Commented Jul 3, 2015 at 16:23
  • %comm% can have spaces, but only like this "abc abc" (Without quotes). When i type " abc" or "abc " it gives me a error. Commented Jul 4, 2015 at 7:46

3 Answers 3

1

(sorry for writing it as an answer, no formatting possible in a comment)

@Marco both methods fail when there are unpaired quotes in the string; both work, if there are paired quotes. I still don't see any advantage using brackets, but in case of poison characters (even spaces!), qoutes work better.

C:\>if "a"b"c" == "a"b"c" echo paired quotes
paired quotes

C:\>if "a"b" == "a"b" echo unpaired quotes
"echo" kann syntaktisch an dieser Stelle nicht verarbeitet werden.

C:\>if [a"b"c] == [a"b"c] echo paired quotes
paired quotes

C:\>if [a"b] == [a"b] echo unpaired quotes
"echo" kann syntaktisch an dieser Stelle nicht verarbeitet werden.

C:\>if ""a"" == ""a""  echo parameter is already in quotes
parameter is already in quotes

C:\>if ["a"] == ["a"]  echo parameter is already in quotes
parameter is already in quotes

C:\>if "a b" =="a b" echo poison character
poison character

C:\>if [a b] ==[a b] echo poison character
"b]" kann syntaktisch an dieser Stelle nicht verarbeitet werden.

for robvanderwoude's problem with %1: easy to overcome by using if "%~1" == "hello" (the ~ removes eventually surrounding quotes)

6
  • Thanks for the comprehensive examples here. Indeed you convinced me to prefer quotes over square brackets as evaluating this seems to be more "stable" in certain situations.
    – Marco
    Commented Jul 4, 2015 at 7:20
  • So the underling question here seems to be: How to handle special characters, resp. how to do quoting correctly as it is not done automatically by the shell after the user input.
    – Marco
    Commented Jul 4, 2015 at 7:28
  • %comm% can have spaces, but only like this "abc abc" (Without quotes). When i type " abc" or "abc " it gives me a error. Commented Jul 4, 2015 at 7:45
  • @Stephan: Now found proper solution how to fix the unbalanced quotes problem --> here
    – Marco
    Commented Jul 6, 2015 at 8:26
  • @Marco: good research, but to make it reliable, you'll have to escape all poison characters (&,|,>...). Quite unhandy, but might be worth the additional work.
    – Stephan
    Commented Jul 6, 2015 at 17:50
1

Okay, finally after reading this article about proper quoting of command line arguments, I came to this solution:

set comm=%comm: =^^ %
set comm=%comm:"=""%

This code is to be placed below your set /p ... line and before your if... condition. It precedes all spaces by the caret sign (1st line) and doubles all double quotes (2nd line). By this, no one of these characters will be treated as poison characters anymore.

Explanation

The caret sign (^) is used by the cmd.exe command line interpreter as the so called "line continuation character", which means to take the next character literally rather than interpret its (possibly) special meaning (including the special meaning of space characters to split up the commands on a command line).

From other discussions here in this thread: The square brackets "[]" are not handled as any special character at all. This is why it still fails when there are spaces inside.

In contrast to this, double quotes are indeed treated as special characters with the meaning that after the first found double quote the interpreter will interpret all upcoming text literally. But the interpreter will do the same only until it finds the next double quote, which is why the if evaluation still fails on unbalanced double quotes. To prevent this, each double quote needs also to be doubled itself.

Hope this helps now.

6
  • better use quotes instead of brackets (prevents from poison characters, for example if [a>b]==[a>b] will fail, if "a>b"=="a>b" works fine.)
    – Stephan
    Commented Jul 3, 2015 at 19:17
  • @Stephan: Seems to be depending what the proposed content of the variable is. Check this or this.
    – Marco
    Commented Jul 3, 2015 at 19:54
  • @Marco: I'm curious; can you give me an example, where brackets work better than qoutes?
    – Stephan
    Commented Jul 3, 2015 at 21:06
  • @Stephan: According to http://www.robvanderwoude.com/parameters.php, quotes do not work when the content itself contains quotes. But I cannot test this here on my Mac - not before next week. Also curious if this is really true.
    – Marco
    Commented Jul 3, 2015 at 21:30
  • When i set %comm% a space(s), it gives "]==[NothingChosen was unexpected at this time" and exits. Can someone test my programm and see what i am talking about? Commented Jul 4, 2015 at 8:06
0

you can tokenize your input (with space as delimiter) and reassemble them:

@echo off
setlocal enabledelayedexpansion

:loop
set "comm="
set /p "comm=[%username%@%computername%] "
set /a count=0
REM tokenize input:
for %%i in (%comm%) do (
  set /a count+=1
  set "word!count!=%%i"
)
REM check for empty input (or spaces only):
if %count% == 0 ( echo no valid input & goto :loop )
REM debug: show all words:
for /l %%i in (1,1,%count%) do echo [!word%%i!]
REM reassemble the words:
set "words="
for /l %%i in (1,1,%count%) do set "words=!words! !word%%i!"
REM remove first space (from assembling):
set "words=%words:~1%"
echo -%words%-
REM do with it whatever has to be done
goto :loop

This works, because two or more consecutive delimiters (spaces) are treated as one.

Not the answer you're looking for? Browse other questions tagged or ask your own question.