The set /p var= command is used to extract the input data that will be stored in the specified variable. Behavior
- If there is data to read, the data is retrieved and stored in the specified variable
- If there is no data to read (data or all data has not been read),
set /p fails (no errors) and the variable does not change .
This second case is the source of the behavior you see.
- "Hello" (from the
echo command) reads at the first iteration - In the second iteration, there is no data to read, but the variable does not change.
Your code (only checking the contents of the variable) does not see the difference between the two cases, since the variable still contains the data from the previous iteration.
If you donβt read any data, this is a valid case for the loop to exit, you can do something like
:start set "msg=" set /p msg="[+] enter msg: " if not defined msg goto :exit
restarting the variable before each reading and leaving if the data has not been read.
It can also be written easier since
:start set /p msg="[+] enter msg: " || goto :exit
This uses the conditional operator || (execute the following command if the previous one did not work) to exit the loop if set /p fails.
edited to adapt to comments:
The desired behavior is to read data from the channel present in the command, but when the data has been read, then set /p should retrieve data from the user. First we need to see how the pipe works.
When cmd processes the pipe operator, two new separate processes are created to process the left and right sides of the pipe.
At this moment, we have three instances of cmd (case in the OP question):
cmd1 : attached to the console running the typed commandcmd2 : run the command on the left side of the channelcmd3 : launch a batch file on the right side of the channel
I / O streams ( stdin is the input stream, stdout is the output stream) associated with each instance:
cmd1 : stdin - current console stdin , stdout - current console stdoutcmd2 : inherits the stdin console from cmd1 , stdout bound to the stdin stream in cmd3cmd3 : stdin attached to the stream stdout cmd2 , stdout inherited from cmd1
In this scenario, cmd3 , which processes the batch file, is not able to get to the console stream stdin active in cmd1 or cmd2 .
So, at the moment I do not see a way to achieve this behavior.