There are several ways of executing different commands on bash
and cmd
with the same script.
cmd
will ignore lines that start with :;
, as mentioned in other answers. It will also ignore the next line if the current line ends with the command rem ^
, as the ^
character will escape the line break and the next line will be treated as a comment by rem
.
As for making bash
ignore the cmd
lines, there are multiple ways. I have enumerated some ways to do that without breaking the cmd
commands:
Non-existent #
command (not recommended)
If there is no #
command available on cmd
when the script is run, we can do this:
# 2>nul & echo Hello cmd! & rem ^
echo 'Hello bash!' #
The #
character at the beginning of the cmd
line makes bash
treat that line as a comment.
The #
character at the end of the bash
line is used to comment out the \r
character, as Brian Tompsett pointed out in his answer. Without this, bash
will throw an error if the file has \r\n
line endings, required by cmd
.
By doing # 2>nul
, we're tricking cmd
to ignore the error of some non-existent #
command, while still executing the command that follows.
Don't use this solution if there is a #
command available on the PATH
or if you have no control over the commands available to cmd
.
Using echo
to ignore the #
character on cmd
We can use echo
with it's output redirected to insert cmd
commands on bash
's commented out area:
echo >/dev/null # >nul & echo Hello cmd! & rem ^
echo 'Hello bash!' #
Since the #
character has no special meaning on cmd
, it is treated as a part of the text to echo
. All we had to do is redirect the output of the echo
command and insert other commands after it.
Empty #.bat
file
echo >/dev/null # 1>nul 2> #.bat
# & echo Hello cmd! & del #.bat & rem ^
echo 'Hello bash!' #
The echo >/dev/null # 1>nul 2> #.bat
line creates an empty #.bat
file while on cmd
(or replaces existing #.bat
, if any), and does nothing while on bash
.
This file will be used by the cmd
line(s) that follows even if there is some other #
command on the PATH
.
The del #.bat
command on the cmd
-specific code deletes the file that was created. You only have to do this on the last cmd
line.
Don't use this solution if a #.bat
file could be on your current working directory, as that file will be erased.
Recomended: using here-document to ignore cmd
commands on bash
:; echo 'Hello bash!';<<:
echo Hello cmd! & ^
:
By placing the ^
character at the end of the cmd
line we're escaping the line break, and by using :
as the here-document delimiter, the delimiter line contents will have no effect on cmd
. That way, cmd
will only execute its line after the :
line is over, having the same behaviour as bash
.
If you want to have multiple lines on both platforms and only execute them at the end of the block, you can do this:
:;( #
:; echo 'Hello' #
:; echo 'bash!' #
:; );<<'here-document delimiter'
(
echo Hello
echo cmd!
) & rem ^
here-document delimiter
As long as there is no cmd
line with exactly here-document delimiter
, this solution should work. You can change here-document delimiter
to any other text.
In all of the presented solutions, the commands will only be executed after the last line, making their behaviour consistent if they do the same thing on both platforms.
Those solutions must be saved to files with \r\n
as line breaks, otherwise they won't work on cmd
.
cp
built in, or vice versa so writing two separate scripts may be pedagogically better than the advanced techniques shown here. – Monkishcp test test2 || copy test test2
does work, although it also prints an error message (and a success message) on Windows.rm test2 || del test2
produces only an error message, but again, does the job. – Monkish