About put / p and the channel and child processes on Windows OS
Just for the test, I expanded your test batch a bit to get four inputs instead of two. Now let's look at this good test.
>type test.txt | test.bat 1st Input:2nd Input:3rd Input:4th Input:1st Input: one and 2nd Input: and 3rd Input: and 4rd Input: "--" >test.bat < test.txt 1st Input:2nd Input:3rd Input:4th Input:1st Input: one and 2nd Input: two and 3rd Input: three and 4rd Input: four "--"
Interestingly, the first example works just like Java code (only the first "set / P" gets the value, and the second works as expected. More interesting if you put the line somewhere in a batch file like this: wmic Process >> TestProcesses.txt by checking TestProcesses.txt in my enviromnet, I see that the first method (pipe) is cmd.exe C:\Windows\system32\cmd.exe /S /D /c" test.bat" , which is not when we use the second (redirect)
I am starting a new test batch (including wmic diagnostics) from java; when we test the test processes, we should see two different processes:
java.exe java -cp .\build\classes javaappcrlf.JavaAppCRLF cmd.exe C:\Windows\system32\cmd.exe /c C:\projects\JavaAppCRLF\test.bat
as in the first method (pipe), we have a separate process for the batch, where "put / p" does not work
In the Pipes and CMD.exe chapter, Pipes and CMD.exe articles
This has several side effects: Any newline characters (CR / LF) in batch_command will also include statements. see fooobar.com/questions/6270 / ... If the batch_command command contains any carriage escape characters; they will need to be doubled so that the escape survives in the new CMD shell.
a related article on stack overflow is also interesting
About C ++ Testing
I am slightly modifying the C ++ program described in Creating a child process with redirected inputs and outputs to read a four-line declaration file that passes its contents to a child process that runs our batch through a pipe and the results match your Java program
Alternative refactoring / workaround
from the above conclusions, it comes that a Java program that reads and writes (temporary) files (... I know this is not the same thing) should work; I successfully tested the working solution by changing the constructor this way
ProcessBuilder builder = new ProcessBuilder( "cmd", "/c", "(C:\\projects\\JavaAppCRLF\\test4.bat < C:\\projects\\JavaAppCRLF\\tmp-test4.in)", ">", "C:\\projects\\JavaAppCRLF\\tmp-test4.out" );
Post Scriptum: interesting note about another shell (ie: bash on "os x" or linux)
AFAIK not all other platforms also suffer from this "problem"; that is, on bash (os x terminal), I did the following test with a script that acts the same as the previous test under Windows:
cd ~/projects/so-test/java-crlf-token/JavaAppCRLF $ cat test.sh #!/bin/bash - # SET /P input1=1st Input: echo -n "1st Input:"; read input1; #SET /P input2=2nd Input: echo -n "2nd Input:"; read input2; #ECHO 1st Input: %input1% and 2nd Input: %input2% echo -n "1st Input: ${input1} and 2nd Input: ${input2}"
then the only thing that was changed in the java program is the link to the script:
ProcessBuilder builder = new ProcessBuilder("/Users/userx/projects/so-test/java-crlf-token/JavaAppCRLF/test.sh");
let's see what happens:
$ cat test.txt abc cde # :pipe $ cat test.txt | test.sh $ cat test.txt | ./test.sh 1st Input:2nd Input:1st Input: abc and 2nd Input: cde # :redirection $ ./test.sh < test.txt 1st Input:2nd Input:1st Input: abc and 2nd Input: cde # :java $ java -cp build/classes/ javaappcrlf.JavaAppCRLF 1st Input:2nd Input:1st Input: foo and 2nd Input: bar