[CLARIFIED] Executing command via FOR results in not recognized

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Maylow
Posts: 35
Joined: 15 Sep 2019 05:33

[CLARIFIED] Executing command via FOR results in not recognized

#1 Post by Maylow » 28 Sep 2022 05:25

This works as expected:

Code: Select all

for /f "tokens=1,* delims=," %b in ("call,dir") do %~b %~c
Results:
C:\Users\xxx>call dir
Volume in drive C is System
Volume Serial Number is 00E1-E8B3

Directory of...
(dir listing)
However, the following gives an error:

Code: Select all

for /f "tokens=1,* delims=," %b in (" ,dir") do %~b %~c
C:\Users\xxx> dir
' ' is not recognized as an internal or external command,
operable program or batch file.
I don't understand why FOR, which I know runs in its own cmd /c context, has a problem with executing ' ' (nothing).
It seems that FOR tries to explicitly run command ' ' (nothing).
This is no problem at all in normal batch context or command line context, but within FOR it produces this error.

For my application I have already found another solution.
I'm just curious and eager to understand this behavior of FOR.

If someone could shed some light on this, I'd be very grateful.
Last edited by Maylow on 28 Sep 2022 07:58, edited 1 time in total.

penpen
Expert
Posts: 1988
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Executing command via FOR results in not recognized

#2 Post by penpen » 28 Sep 2022 07:17

That's not "nothing" - it's a space-character. Since the space-character is no valid command, the error message is correct.
Typically space characters are treated as whitespace characters and will not end up beeing treated as a command.
But you can force cmd to treat the space-character as a command, using the for-command like you did, or escape it with a circumflex accent:

Code: Select all

@echo off
^
  ^


@goto :eof
Note: The two empty lines are neccessary.

penpen

Maylow
Posts: 35
Joined: 15 Sep 2019 05:33

Re: Executing command via FOR results in not recognized

#3 Post by Maylow » 28 Sep 2022 07:50

penpen wrote:
28 Sep 2022 07:17
That's not "nothing" - it's a space-character. Since the space-character is no valid command, the error message is correct.
Typically space characters are treated as whitespace characters and will not end up beeing treated as a command.
But you can force cmd to treat the space-character as a command, using the for-command like you did, or escape it with a circumflex accent:

Code: Select all

@echo off
^
  ^


@goto :eof
Note: The two empty lines are neccessary.

penpen
Ah ok, thanks for this information, I understand it now. The test example you give also demonstrates it clearly.
Is there information about why FOR treats space characters as commands instead of ignoring them? It deviates from default behavior imo.

And might there also be a way to have FOR treat space characters NOT as commands? I suppose not.
I've tried several things, like escape whitespace, replace with ASCII values (tab, backspace, others), etc, they don't work.
Other workarounds I don't like, for example redirecting and thus ignoring the error message, using & to have the second command executed successively.
I would rather have the possibility for FOR to ignore whitespace characters, just like cmd would do under 'normal' circumstances.

I already use an entirely different approach for my application, but I'm still interested in this matter because of possible future obstacles/possibilities.
Thanks again for the clarification you gave :)

penpen
Expert
Posts: 1988
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Executing command via FOR results in not recognized

#4 Post by penpen » 29 Sep 2022 08:45

Maylow wrote:
28 Sep 2022 07:50
Is there information about why FOR treats space characters as commands instead of ignoring them? It deviates from default behavior imo.
It is the default behaviour:
If you escape a character (using the circumflex-character '^'), or add characters when the interpreter expects text starting with escaped characters (using for-variables in the way you did), then it has no special function for the tokenizer that splits the command line string into meaningfull pieces (=tokens). Therefore that escaped character will end up as (a part of) a token.
The interpreter assumes that the first token is the command to execute, which in your above example is a token containing the space-character only.


Maylow wrote:
28 Sep 2022 07:50
And might there also be a way to have FOR treat space characters NOT as commands? I suppose not.
Depending on what you mean. In general use escaped whitespace-characters only where you need them and don't use them if you don't want them.


Maylow wrote:
28 Sep 2022 07:50
I've tried several things, like escape whitespace, replace with ASCII values (tab, backspace, others), etc, they don't work.
Other workarounds I don't like, for example redirecting and thus ignoring the error message, using & to have the second command executed successively.
I would rather have the possibility for FOR to ignore whitespace characters, just like cmd would do under 'normal' circumstances.
Using an escaped whitespace-character is what lead you into that situation.
You want the opposit, which is an unescaped whitespace-character, because you want the lexer to recognize that character to have the special function of beeing 'whitespace'.
Windows batch script doesn't support unescaping characters, so you only have the option to avoid that situation.

I don't know your intended program logic, so there might (or might not) be multiple ways (with different sideeffects) how to help you; for example:

Code: Select all

for /f "tokens=1,* delims=," %%b in (",dir") do %%~b %%~c
for /f "tokens=1,* delims=," %%b in (""",dir") do %%~b %%~c

penpen

Maylow
Posts: 35
Joined: 15 Sep 2019 05:33

Re: Executing command via FOR results in not recognized

#5 Post by Maylow » 30 Sep 2022 04:48

penpen wrote:
29 Sep 2022 08:45
It is the default behaviour:
If you escape a character (using the circumflex-character '^'), or add characters when the interpreter expects text starting with escaped characters (using for-variables in the way you did), then it has no special function for the tokenizer that splits the command line string into meaningfull pieces (=tokens). Therefore that escaped character will end up as (a part of) a token.
The interpreter assumes that the first token is the command to execute, which in your above example is a token containing the space-character only.

Depending on what you mean. In general use escaped whitespace-characters only where you need them and don't use them if you don't want them.

Using an escaped whitespace-character is what lead you into that situation.
You want the opposit, which is an unescaped whitespace-character, because you want the lexer to recognize that character to have the special function of beeing 'whitespace'.
Windows batch script doesn't support unescaping characters, so you only have the option to avoid that situation.

I don't know your intended program logic, so there might (or might not) be multiple ways (with different sideeffects) how to help you; for example:

Code: Select all

for /f "tokens=1,* delims=," %%b in (",dir") do %%~b %%~c
for /f "tokens=1,* delims=," %%b in (""",dir") do %%~b %%~c

penpen
Excellent explanation, many thanks.
Using an escaped whitespace-character is what lead you into that situation.
Yea I figured that out the hard way :wink: With the information you gave me I now understand why.
You want the opposit, which is an unescaped whitespace-character, because you want the lexer to recognize that character to have the special function of beeing 'whitespace'.
Windows batch script doesn't support unescaping characters, so you only have the option to avoid that situation.
Too bad, but not totally unexpected.

I'm going to experiment with the samples you gave.
for /f "tokens=1,* delims=," %%b in (",dir") do %%~b %%~c
for /f "tokens=1,* delims=," %%b in (""",dir") do %%~b %%~c

It was intended for the use of a caller macro under specific circumstances (now I use other approach for this concept).

Post Reply