I'd like to extend @Tiago Becerra Paolini's answer here, which I've upvoted, and my own answer here: Installing & setting up MSYS2 from scratch, including adding all 7 profiles to Windows Terminal....
How to specify in which of the 7 MSYS2 terminals to run a command in Windows from Bash, Command Prompt, & PowerShell
Notes:
- For all commands below, if you are not sure which MSYS2 terminal to use, use the
ucrt64 terminal.
- This assumes that you installed MSYS2 from https://www.msys2.org/ into the default location of
C:\msys64, making msys2_shell.cmd available at C:\msys64\msys2_shell.cmd.
When running from Bash (ex: from within another MSYS2 terminal) in Windows
Important: for any case where you have a command plus arguments, not just a command, be sure to wrap the whole set of "command plus arguments" in single quotes, as shown in the examples below.
# Run in the MSYS2 msys2 terminal
/c/msys64/msys2_shell.cmd -defterm -here -no-start -msys2 -shell bash -c 'some_command_and_args'
# Run in the MSYS2 mingw32 **legacy** terminal
/c/msys64/msys2_shell.cmd -defterm -here -no-start -mingw32 -shell bash -c 'some_command_and_args'
# Run in the MSYS2 mingw64 terminal
/c/msys64/msys2_shell.cmd -defterm -here -no-start -mingw64 -shell bash -c 'some_command_and_args'
# [**RECOMMENDED**] Run in the MSYS2 UCRT64 terminal
/c/msys64/msys2_shell.cmd -defterm -here -no-start -ucrt64 -shell bash -c 'some_command_and_args'
# Run in the MSYS2 clang64 terminal
/c/msys64/msys2_shell.cmd -defterm -here -no-start -clang64 -shell bash -c 'some_command_and_args'
# Run in the MSYS2 clang32 **legacy** terminal
/c/msys64/msys2_shell.cmd -defterm -here -no-start -clang32 -shell bash -c 'some_command_and_args'
# Run in the MSYS2 clangarm64 terminal
/c/msys64/msys2_shell.cmd -defterm -here -no-start -clangarm64 -shell bash -c 'some_command_and_args'
To see which terminal a command is running in, run echo $MSYSTEM in the terminal.
Example runs:
/c/msys64/msys2_shell.cmd -defterm -here -no-start -msys2 -shell bash -c 'echo "$MSYSTEM"'
/c/msys64/msys2_shell.cmd -defterm -here -no-start -mingw32 -shell bash -c 'echo "$MSYSTEM"'
/c/msys64/msys2_shell.cmd -defterm -here -no-start -mingw64 -shell bash -c 'echo "$MSYSTEM"'
/c/msys64/msys2_shell.cmd -defterm -here -no-start -ucrt64 -shell bash -c 'echo "$MSYSTEM"'
/c/msys64/msys2_shell.cmd -defterm -here -no-start -clang64 -shell bash -c 'echo "$MSYSTEM"'
/c/msys64/msys2_shell.cmd -defterm -here -no-start -clang32 -shell bash -c 'echo "$MSYSTEM"'
/c/msys64/msys2_shell.cmd -defterm -here -no-start -clangarm64 -shell bash -c 'echo "$MSYSTEM"'
Example output:
MSYS
MINGW32
MINGW64
UCRT64
CLANG64
CLANG32
CLANGARM64
When running from a Windows Command Prompt
From a Windows Command Prompt, you just need to use Windows-style paths is all. This also works just fine in the MSYS-based Bash terminals in Windows, since MSYS2 terminals do automatic path translation, so you can also run these commands from within an MSYS2 terminal.
Example:
C:\msys64\msys2_shell.cmd -defterm -here -no-start -msys2 -shell bash -c 'echo "$MSYSTEM"'
C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw32 -shell bash -c 'echo "$MSYSTEM"'
C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -shell bash -c 'echo "$MSYSTEM"'
C:\msys64\msys2_shell.cmd -defterm -here -no-start -ucrt64 -shell bash -c 'echo "$MSYSTEM"'
C:\msys64\msys2_shell.cmd -defterm -here -no-start -clang64 -shell bash -c 'echo "$MSYSTEM"'
C:\msys64\msys2_shell.cmd -defterm -here -no-start -clang32 -shell bash -c 'echo "$MSYSTEM"'
C:\msys64\msys2_shell.cmd -defterm -here -no-start -clangarm64 -shell bash -c 'echo "$MSYSTEM"'
Example output: exact same as above.
When running from a Windows PowerShell
From a Windows PowerShell, you need to use the & operator to run the command.
Example:
& "C:\msys64\msys2_shell.cmd" -defterm -here -no-start -msys2 -shell bash -c 'echo "$MSYSTEM"'
& "C:\msys64\msys2_shell.cmd" -defterm -here -no-start -mingw32 -shell bash -c 'echo "$MSYSTEM"'
& "C:\msys64\msys2_shell.cmd" -defterm -here -no-start -mingw64 -shell bash -c 'echo "$MSYSTEM"'
& "C:\msys64\msys2_shell.cmd" -defterm -here -no-start -ucrt64 -shell bash -c 'echo "$MSYSTEM"'
& "C:\msys64\msys2_shell.cmd" -defterm -here -no-start -clang64 -shell bash -c 'echo "$MSYSTEM"'
& "C:\msys64\msys2_shell.cmd" -defterm -here -no-start -clang32 -shell bash -c 'echo "$MSYSTEM"'
& "C:\msys64\msys2_shell.cmd" -defterm -here -no-start -clangarm64 -shell bash -c 'echo "$MSYSTEM"'
Example output: exact same as above.
Bash function to wrap the commands above
You can also create a Bash function to wrap the command in order to significantly simplify the call. Here is a Bash wrapper function:
# Run the passed-in command + arguments inside the MSYS2 UCRT64 terminal
# on Windows
msys2_ucrt64() {
# IMPORTANT!: use `"$*"` instead of `"$@"` here or commands with arguments
# won't work.
/c/msys64/msys2_shell.cmd -defterm -here -no-start -ucrt64 -shell bash -c "$*"
}
# Another example wrapper function
msys2_clang64() {
/c/msys64/msys2_shell.cmd -defterm -here -no-start -clang64 -shell bash -c "$*"
}
Here are some example runs and their outputs. Notice that single quotes around the set of "command plus arguments" are not needed anymore, which helps a lot for really complicated commands and arguments. But, in this case, we want to force the environment variable MSYSTEM to be expanded in the inner, or sub-shell, not the current, or outer shell, so we must surround just $MSYSTEM with single quotes to prevent immediate variable expansion.
Example calls:
msys2_ucrt64 echo '$MSYSTEM'
msys2_clang64 echo '$MSYSTEM'
Example output:
UCRT64
CLANG64
Final answer: a better Bash wrapper function to rule them all!
Let's improve the above wrapper by making the ucrt64 part a parameter to the function so that a single wrapper can handle all 7 MSYS2 terminals.
Let's also surround the call with some marker prints to make it obvious when looking at output in the terminal that it was called from within this specified sub-shell.
# Run the passed-in command + arguments inside the specified MSYS2 terminal
# on Windows.
# - See: https://stackoverflow.com/a/79201770/4561887
#
# Usage: msys2_terminal <terminal> <command> [<args>...]
#
# Example: msys2_terminal ucrt64 echo '$MSYSTEM'
#
msys2_terminal() {
local terminal="$1"
# Remove the first argument from the list of arguments
shift
# IMPORTANT!: use `"$*"` instead of `"$@"` here or commands with arguments
# won't work.
local command="$*"
# Ensure the terminal is one of the 7 MSYS2 terminals.
# - We will also accept `msys` as an alias for `msys2`, since
# `msys2_shell.cmd` does too.
case "$terminal" in
msys|msys2|mingw32|mingw64|ucrt64|clang64|clang32|clangarm64)
;;
*)
echo "Invalid terminal: $terminal"
return 1
;;
esac
# Print the terminal name to make it obvious in the terminal output
echo "--Running in MSYS2 $terminal terminal...START--"
/c/msys64/msys2_shell.cmd -defterm -here -no-start -"$terminal" -shell bash -c "$command"
error_code="$?"
echo "--Running in MSYS2 $terminal terminal...END--"
return "$error_code"
}
# Convenience alias
alias ucrt64="msys2_terminal ucrt64"
Example calls:
msys2_terminal msys echo '$MSYSTEM'
msys2_terminal msys2 echo '$MSYSTEM'
msys2_terminal mingw32 echo '$MSYSTEM'
msys2_terminal mingw64 echo '$MSYSTEM'
msys2_terminal ucrt64 echo '$MSYSTEM' # the preferred terminal
msys2_terminal clang64 echo '$MSYSTEM'
msys2_terminal clang32 echo '$MSYSTEM'
msys2_terminal clangarm64 echo '$MSYSTEM'
Example output:
--Running in MSYS2 msys terminal...START--
MSYS
--Running in MSYS2 msys terminal...END--
--Running in MSYS2 msys2 terminal...START--
MSYS
--Running in MSYS2 msys2 terminal...END--
--Running in MSYS2 mingw32 terminal...START--
MINGW32
--Running in MSYS2 mingw32 terminal...END--
--Running in MSYS2 mingw64 terminal...START--
MINGW64
--Running in MSYS2 mingw64 terminal...END--
--Running in MSYS2 ucrt64 terminal...START--
UCRT64
--Running in MSYS2 ucrt64 terminal...END--
--Running in MSYS2 clang64 terminal...START--
CLANG64
--Running in MSYS2 clang64 terminal...END--
--Running in MSYS2 clang32 terminal...START--
CLANG32
--Running in MSYS2 clang32 terminal...END--
--Running in MSYS2 clangarm64 terminal...START--
CLANGARM64
--Running in MSYS2 clangarm64 terminal...END--
Example call using the ucrt64 alias above:
ucrt64 echo '$MSYSTEM'
Output:
--Running in MSYS2 ucrt64 terminal...START--
UCRT64
--Running in MSYS2 ucrt64 terminal...END--
If you call the msys2_terminal function with an invalid terminal name, you will get an error message and a non-zero return code.
Example run and output. Note that "$?" is the return code of the last command run:
$ msys2_terminal msyss2 echo '$MSYSTEM'
Invalid terminal: msyss2
$ echo "$?"
1
Going further: appropriately handle running on Windows or Linux
See my answer: How to detect the OS from a Bash script?
Example code to run gcc build commands on both Windows and Linux:
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
# For Linux, run normally
"./build_and_run_tests.sh"
elif [[ "$OSTYPE" == "msys" ]]; then
# For Windows, force running the tests inside the MSYS2 UCRT64 terminal
# where we have previously installed gcc with:
#
# ```bash
# # Upgrade all packages
# pacman -Syu
#
# # Install the gcc compiler
# pacman -S mingw-w64-ucrt-x86_64-gcc
# ```
#
msys2_terminal ucrt64 "./build_and_run_tests.sh"
fi
if [ "$?" -ne "0" ]; then
echo "Test FAILED."
fi
# ...
And that's all I know about this topic...
References
- @Tiago Becerra Paolini's answer here
- My own answer here: Installing & setting up MSYS2 from scratch, including adding all 7 profiles to Windows Terminal....
- My answer: How to detect the OS from a Bash script? - see if you're running on Windows or Linux.
- Various chats with GitHub Copilot for help with Bash syntax and things. (This answer is all my own, however, and I've fully manually tested it).
See also
- My answer: How to package a "portable" MSYS2-built Windows application with all required DLLs to run in any Windows environment or terminal
- My answer where I show how to install build tools in the other MSYS2 terminals. I show the install commands for
gcc or clang, cmake, and make, for instance, in each terminal: Detecting your build platform/environment in C and C++ at compile-time in Linux, Windows, GCC, MSYS2, Cygwin, etc.
msys2_shell.cmd -mingw64 -c "help |more"/bin/envand replace/bin/envwith an absolute Windows-style path to the same program. Running mintty probably prevents you from getting the output.