2

I wanted to make my own command prompt. And I wanted a command in it with conditions (e.g. /h or something like that)

This is my command:

if %adm%=="admin /y" (goto add)

I tested it on the original command prompt and it says this:

/y="admin /y" was unexpected at this time.

I tried using carets (the ^ symbol) but it didn't work.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
amegyoushi
  • 524
  • 4
  • 14

2 Answers2

3

The command IF expects at least three arguments on comparing values:

  1. The first argument is the first value: a string (or an integer).
  2. The second argument is the comparison operator: ==, EQU, etc.
  3. The third argument is the second value: a string (or an integer).

How IF executes the comparison is explained in detail in answer on Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files. Run also if /? in a command prompt window to get displayed the help for this command on several window pages.

The argument separator on command line is the space character.

%adm% is replaced by current value of environment variable adm during preprocessing phase of the command line by Windows command interpreter cmd.exe before the command line is executed at all. What is really executed after preprocessing can be seen on temporarily removing @echo off from top of batch file or change it to @echo ON or comment this line, and run the batch file from within a command prompt window instead of double clicking on the batch file.

if admin /y=="admin /y" (goto add)

The command IF interprets admin as first argument. The second argument is /y=="admin /y" which is definitely not a supported comparison operator which is the reason for the error message because that string is really not expected by IF.

An argument string containing a space character or one of the characters &()[]{}^=;!'+,`~<|> requires enclosing the entire argument string in double quotes to get the space and the other characters interpreted as literal characters of an argument string.

So a possible solution is:

if "%adm%"=="admin /y" goto add

This command line in the batch file is expanded during preprocessing to:

if "admin /y" == "admin /y" goto add

It can be seen that Windows command interpreter inserts a space before and after == being the second argument and a valid comparison operator.

The round brackets are removed as command IF is designed by default to execute a single command line. Parentheses are only needed if an ELSE branch is needed too, or multiple command lines should be executed depending on the condition. A command block starting with ( and ending with matching ) cause an extra step during preprocessing phase and should be avoided for that reason if not really needed.

But be aware that any double quote " in string value assigned to adm breaks again the IF condition on using if "%adm%" == "admin /y" goto add in the batch file. This can be seen on using for example

set /P "adm="
if "%adm%" == "admin /y" goto add

And the user enters on execution of this batch file:

" == "" echo rd /Q /S "C:\" & rem "

The command line in the batch file is expanded before execution to:

if "" == "" echo rd /Q /S "C:\"   & rem "" == "admin /y" goto add

So rd /Q /S "C:\" is output and without echo the batch file would start deleting all directories recursive on which the current user has the permissions to delete files and folders.

So if the string assigned to environment variable adm is input by a user of the batch file, it is highly recommended to use delayed environment variable expansion to avoid a modification of the command line during preprocessing phase to an invalid command line or a command line which does something completely different than it is designed for.

setlocal EnableExtensions EnableDelayedExpansion
rem Other command lines in the batch file.
set /P "adm="
if /I "!adm!" == "admin /y" goto add

The environment variable adm is referenced with usage of delayed environment variable expansion and therefore this command line can't be modified for execution by input of the user.

Additionally the optional parameter /I is used to make the string comparison case-insensitive.

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

MS-DOS Batch is expanding your variable %adm% to its value, then trying to compare the last token in that value to the string. To prevent your program from only comparing the last token to the string, you can surround your variable in quotation marks so it will be evaluated to a single string for comparison.


For the correct MS-DOS Batch comparison, your code should look something more like this, which avoids comparing the expanded value of that variable, and instead performs literal comparison of the entire variable's value to the string.

IF "%adm%"=="admin /y"
andrewgu
  • 1,562
  • 14
  • 23