问题
I know the normal behaviour when running an EXE in a batch script is for the batch script to wait for the EXE to exit before continuing, but is there any way to get the batch script to continue execution, but redirect its stdout to the stdin of the EXE?
Basically I'm trying to achieve this neat trick or something similar...
@ECHO OFF
echo This is a windows batch script...
dir /p C:\
C:\cygwin\bash.exe <--- Do some magic here
echo This is a bash shell script...
ls -la /cygdrive/c/
exit
echo We're back to the windows batch script again
REM Note: being able to return to the batch script isn't important
Any ideas on how to achieve this? Thanks.
回答1:
This should work:
@ECHO OFF
echo This is a windows batch script...
dir /p C:\
(
ECHO echo This is a bash shell script...
ECHO ls -la /cygdrive/c/
ECHO exit
) | C:\cygwin\bash.exe
echo We're back to the windows batch script again
EDIT: Reply to the comment
If you want not to add ECHO
to each bash line, you may use this method:
@ECHO OFF
echo This is a windows batch script...
dir /p C:\
rem Get the number of the first line in this file that start with "###"
for /F "delims=:" %%a in ('findstr /N "^###" "%~F0"') do set "line=%%a" & goto break
:break
rem Pass from that line to end of this file to bash.exe
more +%line% "%~F0" | C:\cygwin\bash.exe
echo We're back to the windows batch script again
goto :EOF
#################################################################
# The remainder of this file is a bash script running in cygwin #
#################################################################
echo This is a bash script!!
ls -la /cygdrive/c/
EDIT #2:
I borrowed SonicAtom's method and slightly modified it in order to make it simpler. Here it is:
@ECHO OFF
setlocal
rem This is a magic trick to run the bottom half of this script as a bash script
if not defined _restarted (
set _restarted=true
cmd.exe /Q /D < "%~F0"
rem Put any cleanup commands here
echo/
echo Bash script finished
pause
exit /B
)
cls
"C:\cygwin\bin\bash.exe"
#################################################################
# The remainder of this file is a bash script running in cygwin #
#################################################################
echo This is a bash script!!
ls -la /cygdrive/c/
回答2:
No replies?
Well I found the answer myself:
test.bat:
@ECHO OFF
rem This is a magic trick to run the bottom half of this script as a bash script
if not exist _.bat (
echo @ECHO OFF >_.bat
echo cmd.exe -c ^< %~nx0 >>_.bat
_.bat
rem Put any cleanup commands here
del _.bat
echo.
echo Bash script finished
pause
exit /B
)
cls
"C:\cygwin\bin\bash.exe"
#################################################################
# The remainder of this file is a bash script running in cygwin #
#################################################################
echo This is a bash script!!
ls -la /cygdrive/c/
How it works:
The file starts off as a batch script. It writes another (temporary) batch script which runs another cmd.exe shell, directing the original batch file to cmd.exe as stdin. The original batch file then acts like a text file containing commands typed on the keyboard. It runs bash.exe, and continues to provide stdin to bash. The only disadvantage is that the @ECHO OFF doesn't take effect in the part of the batch file that runs before bash.exe is called. This is because there doesn't seem to be a way to turn off keyboard echoing in cmd.exe.
来源:https://stackoverflow.com/questions/33015036/windows-batch-script-to-redirect-stdout-to-stdin-of-an-exe-weve-just-run