Take the 2-minute tour ×

I would like to keep my .bashrc and .bash_login files in version control so that I can use them between all the computers I use. The problem is I have some OS specific aliases so I was looking for a way to determine if the script is running on Mac OS X, Linux or Cygwin.

What is the proper way to detect the operating system in a Bash script?

share|improve this question
Have you ever considered sharing your configs? I was looking to get the same kind of setup :) –  sorin Apr 9 '12 at 23:21
add comment

12 Answers

up vote 86 down vote accepted

For my .bashrc, I use the following code:

if [[ "$unamestr" == 'Linux' ]]; then
elif [[ "$unamestr" == 'FreeBSD' ]]; then

Then I do somethings like:

if [[ $platform == 'linux' ]]; then
   alias ls='ls --color=auto'
elif [[ $platform == 'freebsd' ]]; then
   alias ls='ls -G'

It's ugly, but it works (you may use 'case' instead of 'if' if you prefer).

share|improve this answer
Why do you set platform from unamestr, instead of just using unamestr? –  csexton Dec 26 '08 at 22:14
I don't know if uname will always give me the same thing, so I make myself independant of its value. –  Nicolas Martyanoff Dec 26 '08 at 23:19
While maybe not the most generic way, this is what I wound up using, so it gets my vote. Thanks Nic. –  csexton Dec 27 '08 at 0:03
Don't use backticks, use the newer clearer syntax: "unamestr = $(uname)". –  unwind Jan 14 '09 at 11:38
Why is that clearer? –  David Winiecki Nov 6 '13 at 17:48
add comment

The bash manpage says that the variable OSTYPE stores the name of the operation system:

OSTYPE Automatically set to a string that describes the operating system on which bash is executing. The default is system- dependent.

It is set to linux-gnu here.

share|improve this answer
Also, $OSTYPE is 'darwin9.0' on my mac (Leopard) and 'cygwin' under Cygwin. –  dF. Dec 26 '08 at 20:33
$OSTYPE is darwin10.0 on SnowLeopard. WTF with the version appended? Means a simple case statement won't work. –  mxcl Dec 3 '09 at 14:52
It's not that big of a deal to remove it: os=${OSTYPE//[0-9.]/} –  ABach Sep 28 '11 at 21:47
case $OSTYPE in darwin*) echo I am a Mac ;; esac –  tripleee Feb 17 '12 at 6:14
@tripleee or for people that are more comfortable with "if" syntax: if [[ $OSTYPE == darwin* ]]; then echo I am a Mac;fi –  Rican7 Feb 5 '13 at 19:28
show 3 more comments

I think the following should work. I'm not sure about the freebsd and win32 ones, though.

if [[ "$OSTYPE" == "linux-gnu" ]]; then
        # ...
elif [[ "$OSTYPE" == "darwin"* ]]; then
        # ...
elif [[ "$OSTYPE" == "cygwin" ]]; then
        # ...
elif [[ "$OSTYPE" == "win32" ]]; then
        # ...
elif [[ "$OSTYPE" == "freebsd"* ]]; then
        # ...
        # Unknown.
share|improve this answer
Thanks for the nice "cut and paste" I can use straight away in my scripts :-) "freebsd" should be "freebsd"* –  Sonia Hamilton Nov 22 '13 at 0:07
add comment

Detecting operating system and CPU type is not so easy to do portably. I have a sh script of about 100 lines that works across a very wide variety of Unix platforms: any system I have used since 1988.

The key elements are

  • uname -p is processor type but is usually unknown on modern Unix platforms.

  • uname -m will give the "machine hardware name" on some Unix systems.

  • /bin/arch, if it exists, will usually give the type of processor.

  • uname with no arguments will name the operating system.

Eventually you will have to think about the distinctions between platforms and how fine you want to make them. For example, just to keep things simple, I treat i386 through i686 , any "Pentium*" and any "AMD*Athlon*" all as x86.

My ~/.profile runs an a script at startup which sets one variable to a string indicating the combination of CPU and operating system. I have platform-specific bin, man, lib, and include directories that get set up based on that. Then I set a boatload of environment variables. So for example, a shell script to reformat mail can call, e.g., $LIB/mailfmt which is a platform-specific executable binary.

If you want to cut corners, uname -m and plain uname will tell you what you want to know on many platforms. Add other stuff when you need it. (And use case, not nesteed if!)

share|improve this answer
According to uname Command, uname without a parameter is equivalent to using the "-s" parameter: "-s Displays the system name. This flag is on by default.". To be explicit one could use "uname -s" instead of "uname". (Elaborated somewhat in an answer to 'Shell output help') –  Peter Mortensen Feb 19 '12 at 11:37
Do you have a link to a github git or pastebin with this 100 script for reliably detecting OS and processor architecture? –  Andrew De Andrade Sep 10 '13 at 18:55
@AndrewDeAndrade I'm ashamed to expose this code to the public. pastebin.com/J66Lj6wf –  Norman Ramsey Sep 14 '13 at 20:44
add comment

I recommend to use this complete bash code

    echo "$1" | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/"

OS=`lowercase \`uname\``
KERNEL=`uname -r`
MACH=`uname -m`

if [ "{$OS}" == "windowsnt" ]; then
elif [ "{$OS}" == "darwin" ]; then
        ARCH=`uname -p`
        OSSTR="${OS} ${REV}(${ARCH} `uname -v`)"
        OSSTR="${OS} `oslevel` (`oslevel -r`)"
    elif [ "${OS}" = "Linux" ] ; then
        if [ -f /etc/redhat-release ] ; then
            DIST=`cat /etc/redhat-release |sed s/\ release.*//`
            PSUEDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//`
            REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
            PSUEDONAME=`cat /etc/SuSE-release | tr "\n" ' '| sed s/VERSION.*//`
            REV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //`
        elif [ -f /etc/mandrake-release ] ; then
            PSUEDONAME=`cat /etc/mandrake-release | sed s/.*\(// | sed s/\)//`
            REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//`
        elif [ -f /etc/debian_version ] ; then
            DIST=`cat /etc/lsb-release | grep '^DISTRIB_ID' | awk -F=  '{ print $2 }'`
            PSUEDONAME=`cat /etc/lsb-release | grep '^DISTRIB_CODENAME' | awk -F=  '{ print $2 }'`
            REV=`cat /etc/lsb-release | grep '^DISTRIB_RELEASE' | awk -F=  '{ print $2 }'`
        if [ -f /etc/UnitedLinux-release ] ; then
            DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]"
        OS=`lowercase $OS`
        DistroBasedOn=`lowercase $DistroBasedOn`
        readonly OS
        readonly DIST
        readonly DistroBasedOn
        readonly PSUEDONAME
        readonly REV
        readonly KERNEL
        readonly MACH


more examples examples here: https://github.com/coto/server-easy-install/blob/master/lib/core.sh

share|improve this answer
You left out the lowercase function, I updated your answer for you. –  Robin Clowers Feb 17 '12 at 5:28
add comment

Try using "uname". For example, in Linux: "uname -a".

According to the manual page, uname conforms to SVr4 and POSIX, so it should be available on Mac OS X and Cygwin too, but I can't confirm that.

BTW: $OSTYPE is also set to linux-gnu here :)

share|improve this answer
Without parameters, uname prints 'Darwin' on Mac OS X (leopard). With -a it prints a whole lot of extra information (kernel version, architecture and something else I cannot decipher). I cannot test on cygwin –  David Rodríguez - dribeas Dec 26 '08 at 20:51
add comment

In bash, use $OSTYPE and $HOSTTYPE, as documented; this is what I do. If that is not enough, and if even uname or uname -a (or other appropriate options) does not give enough information, there’s always the config.guess script from the GNU project, made exactly for this purpose.

share|improve this answer
add comment

I wrote a personal Bash library and scripting framework that uses GNU shtool to do a rather accurate platform detection.

GNU shtool is a very portable set of scripts that contains, among other useful things, the 'shtool platform' command. Here is the output of:

shtool platform -v -F "%sc (%ac) %st (%at) %sp (%ap)"

on a few different machines:

Mac OS X Leopard: 
    4.4BSD/Mach3.0 (iX86) Apple Darwin 9.6.0 (i386) Apple Mac OS X 10.5.6 (iX86)

Ubuntu Jaunty server:
    LSB (iX86) GNU/Linux 2.9/2.6 (i686) Ubuntu 9.04 (iX86)

Debian Lenny:
    LSB (iX86) GNU/Linux 2.7/2.6 (i686) Debian GNU/Linux 5.0 (iX86)

This produces pretty satisfactory results, as you can see. GNU shtool is a little slow, so I actually store and update the platform identification in a file on the system that my scripts call. It's my framework, so that works for me, but your mileage may vary.

Now, you'll have to find a way to package shtool with your scripts, but it's not a hard exercise. You can always fall back on uname output, also.


I missed the post by Teddy about config.guess (somehow). These are very similar scripts, but not the same. I personally use shtool for other uses as well, and it has been working quite well for me.

share|improve this answer
add comment


uname -a

if you want more information

share|improve this answer
add comment

You can simply use pre-defined $OSTYPE variable ie.:

case "$OSTYPE" in
  solaris*) echo "SOLARIS" ;;
  darwin*)  echo "OSX" ;; 
  linux*)   echo "LINUX" ;;
  bsd*)     echo "BSD" ;;
  *)        echo "unknown: $OSTYPE" ;;

Another method is to detect platform based on uname command.

See the following script (ready to include in .bashrc):

# Detect the platform (similar to $OSTYPE)
case $OS in
    alias ls='ls --color=auto'
    alias ls='ls -G'
  'AIX') ;;
  *) ;;

For more ideas, please see my dotfiles on GitHub.

share|improve this answer
add comment

I would suggest avoiding some of these answers. Don't forget that you can choose other forms of string comparison, which would clear up most of the variations, or ugly code offered.

One such solution would be a simple check, such as:

if [[ "$OSTYPE" =~ ^darwin ]]; then

Which has the added benefit of matching any version of Darwin, despite it's version suffix. This also works for any variations of Linux one may expect.

You can see some additional examples within my dotfiles here

share|improve this answer
add comment

Doing the following helped perform the check correctly for ubuntu:

if [[ "$OSTYPE" =~ ^linux ]]; then
    sudo apt-get install <some-package>
share|improve this answer
add comment

Your Answer


