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 (ie, the CygWin ones) are being called, possibly by modifying the path beforehand or fully specifying the executable locations (eg, /c/cygwin/bin/uname ).


Here is the bash script I used to detect three different OS type (GNU/Linux, Mac OS X, Windows NT)

Pay attention

  • 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 use uname .
  • Design

  • Use uname to get the system information ( -s parameter).
  • Use expr and substr 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 because uname -o is not supported on some Operating Systems as Mac OS, Solaris...

    The below snippet does not require bash (ie does not require #!/bin/bash )

    #!/bin/sh
    
    case "$(uname -s)" in
    
       Darwin)
         echo 'Mac OS X'
         ;;
    
       Linux)
         echo 'Linux'
         ;;
    
       CYGWIN*|MINGW32*|MSYS*)
         echo 'MS Windows'
         ;;
    
       # Add here more strings to compare
       # See correspondence table at the bottom of this answer
    
       *)
         echo 'other OS' 
         ;;
    esac
    

    The below Makefile is inspired from Git project ( config.mak.uname ).

    ifdef MSVC     # Avoid the MingW/Cygwin sections
        uname_S := Windows
    else                          # If uname not available => 'not' 
        uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
    endif
    
    # Avoid nesting "if .. else if .. else .. endif endif"
    # because maintenance of matching if/else/endif is a pain
    
    ifeq ($(uname_S),Windows)
        CC := cl 
    endif
    ifeq ($(uname_S),OSF1)
        CFLAGS += -D_OSF_SOURCE
    endif
    ifeq ($(uname_S),Linux)
        CFLAGS += -DNDEBUG
    endif
    ifeq ($(uname_S),GNU/kFreeBSD)
        CFLAGS += -D_BSD_ALLOC
    endif
    ifeq ($(uname_S),UnixWare)
        CFLAGS += -Wextra
    endif
    ...
    

    See also this nice and complete answer about uname -s and Makefile .

    The correspondence table in the bottom of this answer is from Wikipedia article about uname . Please contribute to keep it up-to-date (edit the answer or post a comment). You may also update the Wikipedia article and post a comment to notice me about your contribution ;-)

    See also more sophisticated OS detection as done by the installation scripts of Git LSF.

    Operating System uname -s
    Mac OS X Darwin
    Cygwin 32-bit (Win-XP) CYGWIN_NT-5.1
    Cygwin 32-bit (Win-7 32-bit) CYGWIN_NT-6.1
    Cygwin 32-bit (Win-7 64-bit) CYGWIN_NT-6.1-WOW64
    Cygwin 64-bit (Win-7 64-bit) CYGWIN_NT-6.1
    MinGW (Windows 7 32-bit) MINGW32_NT-6.1
    MinGW (Windows 10 64-bit) MINGW64_NT-10.0
    Interix (Services for UNIX) Interix MSYS MSYS_NT-6.1
    Android Linux
    coreutils Linux
    CentOS Linux
    Fedora Linux
    Gentoo Linux
    Red Hat Linux Linux
    Linux Mint Linux
    openSUSE Linux
    Ubuntu Linux
    Unity Linux Linux
    Manjaro Linux Linux
    OpenWRT r40420 Linux
    Debian (Linux) Linux
    Debian (GNU Hurd) GNU
    Debian (kFreeBSD) GNU/kFreeBSD
    FreeBSD FreeBSD
    NetBSD NetBSD
    DragonFlyBSD DragonFly
    Haiku Haiku
    NonStop NONSTOP_KERNEL
    QNX QNX
    ReliantUNIX ReliantUNIX-Y
    SINIX SINIX-Y
    Tru64 OSF1
    Ultrix ULTRIX
    IRIX 32 bits IRIX
    IRIX 64 bits IRIX64
    MINIX Minix
    Solaris SunOS
    UWIN (64-bit Windows 7) UWIN-W7
    SYS$UNIX:SH on OpenVMS IS/WB
    z/OS USS OS/390
    Cray sn5176
    (SCO) OpenServer SCO_SV
    (SCO) System V SCO_SV
    (SCO) UnixWare UnixWare
    IBM AIX AIX
    IBM i with QSH OS400
    HP-UX HP-UX

    链接地址: http://www.djcxy.com/p/17508.html

    上一篇: 如何通过主机从外部连接到VirtualBox guest?

    下一篇: 如何检查在Cygwin,Mac或Linux上运行?