How to check if running in Cygwin, Mac or Linux?
I have a shell script that is used both on Windows/Cygwin and Mac and Linux. It needs slightly different variables for each versions.
How can a shell/bash script detect whether it is running in Cygwin, on a Mac or开发者_开发百科 in Linux?
Usually, uname
with its various options will tell you what environment you're running in:
pax> uname -a
CYGWIN_NT-5.1 IBM-L3F3936 1.5.25(0.156/4/2) 2008-06-12 19:34 i686 Cygwin
pax> uname -s
CYGWIN_NT-5.1
And, according to the very helpful schot
(in the comments), uname -s
gives Darwin
for OSX and Linux
for Linux, while my Cygwin gives CYGWIN_NT-5.1
. But you may have to experiment with all sorts of different versions.
So the bash
code to do such a check would be along the lines of:
unameOut="$(uname -s)"
case "${unameOut}" in
Linux*) machine=Linux;;
Darwin*) machine=Mac;;
CYGWIN*) machine=Cygwin;;
MINGW*) machine=MinGw;;
*) machine="UNKNOWN:${unameOut}"
esac
echo ${machine}
Note that I'm assuming here that you're actually running within CygWin (the bash
shell of it) so paths should already be correctly set up. As one commenter notes, you can run the bash
program, passing the script, from cmd
itself and this may result in the paths not being set up as needed.
If you are doing that, it's your responsibility to ensure the correct executables (i.e., the CygWin ones) are being called, possibly by modifying the path beforehand or fully specifying the executable locations (e.g., /c/cygwin/bin/uname
).
Detect three different OS types (GNU/Linux, Mac OS X, Windows NT)
Notes
- In your bash script, use
#!/usr/bin/env bash
instead of#!/bin/sh
to prevent the problem caused by/bin/sh
linked to different default shell in different platforms, or there will be error like unexpected operator, that's what happened on my computer (Ubuntu 64 bits 12.04). - Mac OS X 10.6.8 (Snow Leopard) do not have
expr
program unless you install it, so I just useuname
.
Design
- Use
uname
to get the system information (-s
parameter). - Use
expr
andsubstr
to deal with the string. - Use
if
elif
fi
to do the matching job. - You can add more system support if you want, just follow the
uname -s
specification.
Implementation
#!/usr/bin/env bash
if [ "$(uname)" == "Darwin" ]; then
# Do something under Mac OS X platform
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
# Do something under GNU/Linux platform
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then
# Do something under 32 bits Windows NT platform
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
# Do something under 64 bits Windows NT platform
fi
Testing
- Linux (Ubuntu 12.04 LTS, Kernel 3.2.0) tested OK.
- OS X (10.6.8 Snow Leopard) tested OK.
- Windows (Windows 7 64 bit) tested OK.
What I learned
- Check for both opening and closing quotes.
- Check for missing parentheses and braces {}
References
- [1] uname - wikipedia
- [2] shell script syntax error: unexpected end of file
- [3] Detect the OS from a Bash script
- [4] BASH Programming Introduction HOW-TO
Use uname -s
(--kernel-name
) because uname -o
(--operating-system
) is not supported on some Operating Systems such as Mac OS and Solaris. You may also use just uname
without any argument since the default argument is -s
(--kernel-name
).
To distinguish WSL from Linux, einarmagnus recommends uname -sr
(--kernel-name --kernel-release
) as proposed in the following script.
精彩评论