We can use bash in our scripts now in Win10

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
OperatorGK
Posts: 66
Joined: 13 Jan 2015 06:55

We can use bash in our scripts now in Win10

#1 Post by OperatorGK » 18 Apr 2016 11:00

With new Win10 update it's now possible to execute bash (or sh) scripts from command line.
I made a simple hybrid bat-bash file which works fine for me on Windows 10 Build 14316:

Code: Select all

@goto :batch_part

# Bash part
echo Hello from bash!
echo Normal syntax for variable expansion doesnt work here: %a%
echo However, using syntax \"\$name\" we can expand even CMD.EXE variables: "\$A"=$A
echo Note: variables are case-sensivite, CMD.EXE variables are uppercase
echo Other features from bash should also work
exit

:batch_part
@echo off
set a=b
bash "%~f0"
echo.
echo End of bash part
exit /b

Output:

Code: Select all

D:\CMD\my\bash_hybrid.bat: line 1: @goto: command not found
Hello from bash!
Normal syntax for variable expansion doesnt work here: %a%
However, using syntax "$name" we can expand even CMD.EXE variables: $A=b
Note: variables are case-sensivite, CMD.EXE variables are uppercase
Other features from bash should also work

End of bash part

If someone finds a better way to make hybrid batch-bash files, please post it here.

EDIT: Corrected windows version.

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

Re: We can use bash in our scripts now in Win10

#2 Post by penpen » 18 Apr 2016 19:21

I cannot test it, but i think something like this may work (untested):

Code: Select all

: > /dev/null # ^
echo "\" >nul
@goto :batch
" > /dev/null 2>&1

echo bash part
exit 0

:batch
@echo off
echo batch part
bash "%~f0"
goto :eof


penpen

Edit: I missed the echo off part...; now added it
Last edited by penpen on 19 Apr 2016 06:09, edited 2 times in total.

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: We can use bash in our scripts now in Win10

#3 Post by siberia-man » 19 Apr 2016 02:37

bash-in-batch hybrid can be like vbs-in-batch one as it is shown here viewtopic.php?f=3&t=5543&start=30#p37780

Code: Select all

: # @echo off
: # echo:==== cmd
: # bash "%~f0" %*
: # echo:==== cmd again
: # goto :EOF

echo "==== bash"
for n in "$@" ; do echo "$n" ; done
exit


Description of the trick:
Assuming bash is described in %PATH%
First 5 lines are batch/cmd code invoking bash
The syntax is as follows:

Code: Select all

COLON (:) SPACE (ascii32) HASH (#) SPACE (ascii32) SUB (ascii26) any-valid-cmd-command


How cmd interprets this:
The colon symbol is the marker of cmd label so the rest of the line shouldn't be executed but SUB (ascii26) symbol is considered as line delimiter so the rest of line after SUB char is the normal command that will be interpreted and executed.

How bash interprets this:
The colon symbol is the empty command with the following hash symbol that is the marker of bash comment, so the rest of the line will never be executed.

In summary:
cmd executes first 5 lines (until goto :EOF) and exits. One of this lines has the command invoking bash with the same file as the bash script. Bash executes all lines but the first 5 lines are empty commands and comments and do not produce any useful work. The rest of the file is assumed as the fruitful bash script that is executed and does something useful.

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: We can use bash in our scripts now in Win10

#4 Post by einstein1969 » 19 Apr 2016 04:24

thanks for the explain siberia-man!

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

Re: We can use bash in our scripts now in Win10

#5 Post by penpen » 19 Apr 2016 06:13

I've updated my above post where i've forgotten to handle the "echo":
May someone test it?

Actually i don't have access to win10, and don't know if (the "windows") bash supports multiline echoes,
and i don't remind how the tilde character is used in bash.


penpen

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: We can use bash in our scripts now in Win10

#6 Post by ShadowThief » 19 Apr 2016 07:02

penpen wrote:I've updated my above post where i've forgotten to handle the "echo":
May someone test it?

Actually i don't have access to win10, and don't know if (the "windows") bash supports multiline echoes,
and i don't remind how the tilde character is used in bash.


penpen

~ is the bash version of %userprofile%

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: We can use bash in our scripts now in Win10

#7 Post by siberia-man » 19 Apr 2016 07:11

Another hybrid as a combination of two solutions above. It is a bit simpler than mine or by penpen but has more limitations.

Code: Select all

: <<____CMD____

@echo off
echo:cmd
bash "%~f0" %*
echo:cmd again
goto :EOF

____CMD____

echo "bash"
for n in "$@" ; do echo "$n" ; done
exit 0


How does it work

1. The first line is assumed by cmd.exe as a label and is not interpreted the rest of the line after the colon. Further code is considered as valid batch script until the ending goto :EOF. This part invokes the same file as a bash script, as well

2. The colon symbol in bash is empty command and does nothing; following <<____CMD____ is the beginning marker of heredoc until the ending marker ____CMD____. The full content of heredoc is assumed as the argument of the command colon. So it does nothing in bash, as well. The rest of the file is interpreted as valid bash script.

Assumptions and limitations:
-- bash is assumed in %PATH%
-- batch prolog shouldn't have any duplicates of the heredoc markers (I guess ____CMD____ is good candidate to be a marker)
-- batch part shouldn't have any bash command substitutions, for example, $( ... ), or ` ... `

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

Re: We can use bash in our scripts now in Win10

#8 Post by penpen » 19 Apr 2016 07:22

ShadowThief wrote:
penpen wrote:I've updated my above post where i've forgotten to handle the "echo":
May someone test it?

Actually i don't have access to win10, and don't know if (the "windows") bash supports multiline echoes,
and i don't remind how the tilde character is used in bash.


penpen

~ is the bash version of %userprofile%
Thanks for the info, i'm sorry to have to say oops :oops: :
I meant the circumflex accent character (^).

penpen

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: We can use bash in our scripts now in Win10

#9 Post by siberia-man » 17 May 2016 04:50

The hybrid by penpen can be improved to avoid some possible troubles if the text within multiline text for some reasons will contain the command substitutions:

Code: Select all

: > /dev/null # ^
echo ' > nul
@echo off
echo:==== cmd
bash "%~f0" %*
echo:==== cmd again
goto :eof
' > /dev/null

echo "==== bash"
for n in "$@" ; do echo "$n" ; done
exit


Also I have improved my last version (with heredoc). There is starting heredoc marker arounded by quotes to avoid interpreting of hererdoc and consider its content as is:

Code: Select all

: << '____CMD____'

@echo off
echo:==== cmd
bash "%~f0" %*
echo:==== cmd again
goto :eof

____CMD____

echo "==== bash"
for n in "$@" ; do echo "$n" ; done
exit 0


As the conclusion. If I would like to start using the cmd+bash hybrid, I would have prefered this one (the quoted heredoc). :)

Judago
Posts: 15
Joined: 04 Nov 2011 07:59

Re: We can use bash in our scripts now in Win10

#10 Post by Judago » 18 May 2016 08:24

I'm not sure about win10, but in bash on linux[GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)] this seems to do ok:

Code: Select all

echo -n # > nul & goto batch


A true hyrbrid that is cross platform would also need a shebang, "#!/usr/bin/env bash" of similar.

Edit: I just realised that the prompt and command will likely be echo's by cmd. So much for my one liner.
Last edited by Judago on 18 May 2016 09:28, edited 1 time in total.

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: We can use bash in our scripts now in Win10

#11 Post by Squashman » 18 May 2016 09:28

Judago wrote:I'm not sure about win10, but in bash on linux[GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)] this seems to do ok:

Code: Select all

echo -n # > nul & goto batch


A true hyrbrid that is cross platform would also need a shebang, "#!/usr/bin/env bash" of similar.


Hi Judago,
Nice to see you around. :)

Judago
Posts: 15
Joined: 04 Nov 2011 07:59

Re: We can use bash in our scripts now in Win10

#12 Post by Judago » 18 May 2016 09:31

Hi Squashman, nice to see you too.

Unfortunately I just realized that cmd will spit out unwanted text:

Code: Select all

W:\here\ever>echo -n #   1>nul  & goto batch

jfl
Posts: 226
Joined: 26 Oct 2012 06:40
Location: Saint Hilaire du Touvet, France
Contact:

Re: We can use bash in our scripts now in Win10

#13 Post by jfl » 19 Oct 2016 10:42

The above examples do not work for me, in Windows 10 build 14393.

There are two problems:
  • Ubuntu bash does not find the windows pathname of the script, as its drive letter and \ separators mean nothing to it.
    Resolved by converting the Windows name to the Linux name.
  • Also the batch file contains CRLF line endings, which make Ubuntu bash spit an error on each line.
    Resolved by using `tr -d '\r'` and piping the output to a second instance of bash.

After a bit of experimentation, I ended up with this hybrid script that works:

Code: Select all

: Batch label and beginning of Bash inline block << :Bash_Section
@echo off
echo Starting in batch.

:# Convert the Windows path of this script to its Linux path
set "SCRIPT=%~f0"
for %%d in (A.a B.b C.c D.d E.e F.f G.g H.h I.i J.j K.k L.l M.m N.n O.o P.p Q.q R.r S.s T.t U.u V.v W.w X.x Y.y Z.z) do (
  for /f "tokens=1,2 delims=." %%l in ('echo %%d') do call set "SCRIPT=%%SCRIPT:%%l:=/mnt/%%m%%"
)
set "SCRIPT=%SCRIPT:\=/%"

set CMD=bash -c "tr -d '\r' < '%SCRIPT%' | bash -"
echo %CMD%
%CMD%

echo Back in batch.
exit /b

:Bash_Section
echo "Hello $USER from bash!"
exit

This outputs:

Code: Select all

Starting in batch.
bash -c "tr -d '\r' < '/mnt/c/Users/Larvoire/Documents/Temp/t.bat' | bash -"
Hello root from bash!
Back in batch.

I tried to avoid the file name conversion by redirecting bash standard input to the batch file. For example:

Code: Select all

<%0 bash -c "tr -d '\r' | bash -"

But this fails with Error: 0x80070057.
Any idea as to why this does not work?

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

Re: We can use bash in our scripts now in Win10

#14 Post by penpen » 19 Oct 2016 12:38

jfl wrote:Also the batch file contains CRLF line endings, which make Ubuntu bash spit an error on each line.
The batch only contains CRLF endings, if you use an editor (for example notepad.exe) that use this line ending.
So just use another editor, that stores only LF endings - the batch will still run without errors.


jfl wrote:But this fails with Error: 0x80070057.
Any idea as to why this does not work?
The Linux subsystem for Windows 10 64 bit is still under developement, so there might be changes on every windows update.
One issue i know is, that enabling 'Legacy mode' of cmd.exe will disable the Linux subsystem,
so you have to deactivate this mode in the cmd properties (and restart cmd.exe - maybe a reboot is needed).


Sidenote:
I still haven't tested my solution (don't have win 10 64 Bit), but i thought OperatorGK has tested 'bash "%~f0"' successfully (see: Output in the OP),
so i'm a bit confused that this doesn't work for you, so i wonder if this command line option has been removed by one of the last windows updates,
or if you have also have manually installed "external executables" which are executed instead of the 'windows featured bash'
(although i think this is improbable because of the error you have got).


penpen

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: We can use bash in our scripts now in Win10

#15 Post by Squashman » 19 Oct 2016 14:01

jfl wrote:[*] Also the batch file contains CRLF line endings, which make Ubuntu bash spit an error on each line.
Resolved by using `tr -d '\r'` and piping the output to a second instance of bash.[/list]

Hmm. I don't like that. We are working in a Windows Environment which uses CRLF as its standard. Why would they not account for this in the version of BASH they are using on Windows.

Post Reply