How to detect the OS from a Bash script?
Asked Answered
A

22

801

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?

Airla answered 26/12, 2008 at 20:27 Comment(6)
Have you ever considered sharing your configs? I was looking to get the same kind of setup :)Leander
@Leander I know it's an old comment, but if you're still curious, I've been building ProfileGem which lets you configure pluggable bash environments for all your machines.Testimony
@Testimony profilegem seems to have been moved here bitbucket.org/dimo414/profilegem. As far as sharing bash configs in general, try some of these dotfiles projects: github.com/…Curtal
@Curtal thanks for the updated link, sorry I can't edit my comment. I'd welcome feedback or bugs if you're experimenting with ProfileGem!Testimony
Alas BitBucket is turning down Mercurial support, so I have to update my link again :( github.com/dimo414/ProfileGem is the new home.Testimony
For those of you looking for a "cross-platform solution" (as in one which works on both WSL/macOS/Linux, check this answer - https://mcmap.net/q/20158/-how-to-detect-the-os-from-a-bash-scriptVegetate
E
892

I think the following should work. I'm not sure about win32 though.

if [[ "$OSTYPE" == "linux-gnu"* ]]; then
        # ...
elif [[ "$OSTYPE" == "darwin"* ]]; then
        # Mac OSX
elif [[ "$OSTYPE" == "cygwin" ]]; then
        # POSIX compatibility layer and Linux environment emulation for Windows
elif [[ "$OSTYPE" == "msys" ]]; then
        # Lightweight shell and GNU utilities compiled for Windows (part of MinGW)
elif [[ "$OSTYPE" == "win32" ]]; then
        # I'm not sure this can happen.
elif [[ "$OSTYPE" == "freebsd"* ]]; then
        # ...
else
        # Unknown.
fi
Equalize answered 21/12, 2011 at 22:46 Comment(20)
On Windows, you will get msys for Git Bash/msysGit, and cygwin for CygwinEscalate
This answer including how to detect for Windows is good. I'm also using Mingw32 and it comes up as msysOctangle
Interesting.. Mac OSX would still give 'darwin'.Henriquez
My OSX Yosemit (10.10.5) has no $OSTYPE.Mutiny
OS X El Capitan: $ echo $OSTYPE => darwin15Seasoning
Something that tripped me up, when you replace the comment with a command - make sure to end with with ;.Melodic
When I add a command like source somefile ; , I get syntax error near unexpected token elif.Kevel
Anybody have an idea on how to distinguish between WSL and vanilla Linux? WSL is technically linux so uname and OSTYPE don't work.Star
@DavidA.French grep Microsoft /proc/version should work, according to github.com/Microsoft/WSL/issues/423.Blankly
Thanks @Blankly I ended up using UNAMECHECK=$(uname -a); if [[ $UNAMECHECK == *"Microsoft"* ]]Star
linux-android? for TermuxDulcimer
@Penn My Android terminal doesn't use BASH by default (not sure why). But after logging into the BASH shell, OSTYPE was set to "android-eabi". This terminal is strange. I think Termux uses BASH or another popular shell, so OSTYPE is probably set in it. I believe the correct code would be elif [[ "$OSTYPE" == "android"* ]]; then.Briannebriano
@Briannebriano I actually encountered this behaviour too. I tried exactly the same fix as you but with [ not [[, hence globbing didn't work so I ended up using grep (because I need to support non-bash systems)Dulcimer
Nice but I would use a switch case here rather than the if/else sequence.Godliman
The value is msys in MSYS2 as well.Daggna
"linux-gnu" should be "linux-gnu"*. As far I tested, Arch Linux ARM on Raspberry Pi 4 and Raspbian Buster on Raspberry Pi 3 returns "linux-gnueabihf".Jillayne
WSL also returns linux-gnu. Check /proc/version for string "Microsoft" to detect WSL (via: if grep -q -i microsoft /proc/version; then)Ridgley
Latest macos on Github Actions gives "darwin19" :/Innovation
This one doesn't seem to work in dockerVillainy
I found a useful list of possible $OSTYPE values.Mariejeanne
C
320

For my .bashrc, I use the following code:

platform='unknown'
unamestr=$(uname)
if [[ "$unamestr" == 'Linux' ]]; then
   platform='linux'
elif [[ "$unamestr" == 'FreeBSD' ]]; then
   platform='freebsd'
fi

Then I do somethings like:

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

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

Charlatanism answered 26/12, 2008 at 20:36 Comment(10)
Why do you set platform from unamestr, instead of just using unamestr?Airla
I don't know if uname will always give me the same thing, so I make myself independant of its value.Charlatanism
While maybe not the most generic way, this is what I wound up using, so it gets my vote. Thanks Nic.Airla
Don't use backticks, use the newer clearer syntax: "unamestr = $(uname)".Chela
From a quick glance, the backticks could resemble a string.Katt
@david-winiecki Because if you need to nest commands e.g. $(command-1 $(command-2))Malversation
Wouldn't it be much better to do: platform="$(uname | tr '[:upper:]' '[:lower:]')" and then definitely handle in a case? It just seems weird to hardcode a dependency on very specific output.Joshua
to detect a mac if you execute this in the terminal you will get darwin. echo uname DarwinDrippy
@uwind or use whatever you like best and quit preaching. there's no one single best way.Algid
Why do you have to type '[[' ']]' ? Why wouldn't '[' ']' work?Houseroom
O
304

The bash manpage says that the variable OSTYPE stores the name of the operating 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.

Organism answered 26/12, 2008 at 20:31 Comment(11)
Also, $OSTYPE is 'darwin9.0' on my mac (Leopard) and 'cygwin' under Cygwin.Peripteral
In Debian Testing, $OSTYPE also contains linux-gnu.Eustoliaeutectic
$OSTYPE is darwin10.0 on SnowLeopard. WTF with the version appended? Means a simple case statement won't work.Pages
It's not that big of a deal to remove it: os=${OSTYPE//[0-9.]/}Mauk
case $OSTYPE in darwin*) echo I am a Mac ;; esacVaccinate
darwin11 on Lion, for reference.Fond
@Vaccinate or for people that are more comfortable with "if" syntax: if [[ $OSTYPE == darwin* ]]; then echo I am a Mac;fiTokharian
My OSX Yosemit (10.10.5) has no $OSTYPE.Mutiny
@Mutiny strange, I have the same OS version and my $OSTYPE is darwin14.Skilled
Appears to be a non POSIX Bash extension BTW, determined via grepping dowloaded POSIX.Piccalilli
Nice. However doesnt help when WSL and WSL2 on windows also report the same value and you need to know the difference someteims. Posted my own answer how I solved thi.sVagus
R
266

$OSTYPE

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

case "$OSTYPE" in
  solaris*) echo "SOLARIS" ;;
  darwin*)  echo "OSX" ;; 
  linux*)   echo "LINUX" ;;
  bsd*)     echo "BSD" ;;
  msys*)    echo "WINDOWS" ;;
  cygwin*)  echo "ALSO WINDOWS" ;;
  *)        echo "unknown: $OSTYPE" ;;
esac

However it's not recognized by the older shells (such as Bourne shell).


uname

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)
OS="`uname`"
case $OS in
  'Linux')
    OS='Linux'
    alias ls='ls --color=auto'
    ;;
  'FreeBSD')
    OS='FreeBSD'
    alias ls='ls -G'
    ;;
  'WindowsNT')
    OS='Windows'
    ;;
  'Darwin') 
    OS='Mac'
    ;;
  'SunOS')
    OS='Solaris'
    ;;
  'AIX') ;;
  *) ;;
esac

You can find some practical example in my .bashrc.


Here is similar version used on Travis CI:

case $(uname | tr '[:upper:]' '[:lower:]') in
  linux*)
    export TRAVIS_OS_NAME=linux
    ;;
  darwin*)
    export TRAVIS_OS_NAME=osx
    ;;
  msys*)
    export TRAVIS_OS_NAME=windows
    ;;
  *)
    export TRAVIS_OS_NAME=notset
    ;;
esac
Representative answered 25/8, 2013 at 23:43 Comment(3)
The $OSTYPE check is missing a branch for cygwin, which would indicate a windows machine. The uname check would not work properly either, on cygwin uname returns "CYGWIN_NT-10.0" and on MinGW uname returns "MINGW64_NT-10.0".Signe
alias ls='/bin/ls -G' is actually the safe option, in the context of OS-based fags see superuser.com/a/1299969/84662Fanning
I suggest using uname, Oracle have glossed convention and put a free version string with their OSTYPE ==> solaris2.11. uname is a little cleaner and less work to do.Bedroom
K
48

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 nested if!)

Kildare answered 26/12, 2008 at 21:7 Comment(4)
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')Pelite
Do you have a link to a github git or pastebin with this 100 script for reliably detecting OS and processor architecture?Tripod
@AndrewDeAndrade I'm ashamed to expose this code to the public. pastebin.com/J66Lj6wfKildare
so how about uname -s?Bibelot
I
43

I recommend to use this complete bash code

lowercase(){
    echo "$1" | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/"
}

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

if [ "{$OS}" == "windowsnt" ]; then
    OS=windows
elif [ "{$OS}" == "darwin" ]; then
    OS=mac
else
    OS=`uname`
    if [ "${OS}" = "SunOS" ] ; then
        OS=Solaris
        ARCH=`uname -p`
        OSSTR="${OS} ${REV}(${ARCH} `uname -v`)"
    elif [ "${OS}" = "AIX" ] ; then
        OSSTR="${OS} `oslevel` (`oslevel -r`)"
    elif [ "${OS}" = "Linux" ] ; then
        if [ -f /etc/redhat-release ] ; then
            DistroBasedOn='RedHat'
            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/\ .*//`
        elif [ -f /etc/SuSE-release ] ; then
            DistroBasedOn='SuSe'
            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
            DistroBasedOn='Mandrake'
            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
            DistroBasedOn='Debian'
            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 }'`
        fi
        if [ -f /etc/UnitedLinux-release ] ; then
            DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]"
        fi
        OS=`lowercase $OS`
        DistroBasedOn=`lowercase $DistroBasedOn`
        readonly OS
        readonly DIST
        readonly DistroBasedOn
        readonly PSUEDONAME
        readonly REV
        readonly KERNEL
        readonly MACH
    fi

fi
echo $OS
echo $KERNEL
echo $MACH

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

Infection answered 25/9, 2010 at 7:0 Comment(6)
You left out the lowercase function, I updated your answer for you.Indign
Once you know it's Linux, if you're just poking around (not trying to automate finding out) it seems like easiest move is to just ls /etc and look for "blah-release" - whatever blah is, that's the Linux OS - CentOS, Ubuntu, etcTimpani
I edited because some of the references to OS variable were written as "{$OS}" I changed them to "${OS}" that's the right way, I tested itArmyn
would you consider to add "echo ${OS}" at the very end of the script?Bazaar
This is a lot of work for a big mystery at the end (no information printed). I second that it needs echo $OS at the end.Ruphina
I prefer using tr '[A-Z]' '[a-z]' over the lengthy sed pattern in the lowercase function.Gravedigger
C
21

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

Captain answered 3/5, 2012 at 21:59 Comment(1)
Link isn't working..Hejira
A
14
uname

or

uname -a

if you want more information

Altorelievo answered 26/12, 2008 at 20:33 Comment(0)
V
14

This is what I use if anyone is interested in detecting WSL vs WSL version 2 as well. This works in ZSH as well as BASH.

#!/usr/bin/env bash

unameOut=$(uname -a)
case "${unameOut}" in
    *Microsoft*)     OS="WSL";; #must be first since Windows subsystem for linux will have Linux in the name too
    *microsoft*)     OS="WSL2";; #WARNING: My v2 uses ubuntu 20.4 at the moment slightly different name may not always work
    Linux*)     OS="Linux";;
    Darwin*)    OS="Mac";;
    CYGWIN*)    OS="Cygwin";;
    MINGW*)     OS="Windows";;
    *Msys)     OS="Windows";;
    *)          OS="UNKNOWN:${unameOut}"
esac

echo ${OS};

Update: I also added this to my script for detecting M1 vs a normal Mac.

if [[ ${OS} == "Mac" ]] && sysctl -n machdep.cpu.brand_string | grep -q 'Apple M1'; then
    OS="MacM1"
fi
Vagus answered 9/8, 2021 at 2:47 Comment(0)
H
12

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 :)

Hush answered 26/12, 2008 at 20:33 Comment(1)
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 cygwinOrb
T
11

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.

Tezel answered 14/1, 2009 at 11:24 Comment(0)
R
11

Below it's an approach to detect Debian and RedHat based Linux OS making use of the /etc/lsb-release and /etc/os-release (depending on the Linux flavor you're using) and take a simple action based on it.

#!/bin/bash
set -e

YUM_PACKAGE_NAME="python python-devl python-pip openssl-devel"
DEB_PACKAGE_NAME="python2.7 python-dev python-pip libssl-dev"

 if cat /etc/*release | grep ^NAME | grep CentOS; then
    echo "==============================================="
    echo "Installing packages $YUM_PACKAGE_NAME on CentOS"
    echo "==============================================="
    yum install -y $YUM_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Red; then
    echo "==============================================="
    echo "Installing packages $YUM_PACKAGE_NAME on RedHat"
    echo "==============================================="
    yum install -y $YUM_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Fedora; then
    echo "================================================"
    echo "Installing packages $YUM_PACKAGE_NAME on Fedorea"
    echo "================================================"
    yum install -y $YUM_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Ubuntu; then
    echo "==============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Ubuntu"
    echo "==============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Debian ; then
    echo "==============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Debian"
    echo "==============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Mint ; then
    echo "============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Mint"
    echo "============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Knoppix ; then
    echo "================================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Kanoppix"
    echo "================================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 else
    echo "OS NOT DETECTED, couldn't install package $PACKAGE"
    exit 1;
 fi

exit 0

Output example for Ubuntu Linux:

delivery@delivery-E5450$ sudo sh detect_os.sh
[sudo] password for delivery: 
NAME="Ubuntu"
===============================================
Installing packages python2.7 python-dev python-pip libssl-dev on Ubuntu
===============================================
Ign http://dl.google.com stable InRelease
Get:1 http://dl.google.com stable Release.gpg [916 B]                          
Get:2 http://dl.google.com stable Release [1.189 B] 
...            
Rentsch answered 20/1, 2017 at 12:36 Comment(0)
K
10

I wrote these sugars in my .bashrc:

if_os () { [[ $OSTYPE == *$1* ]]; }
if_nix () { 
    case "$OSTYPE" in
        *linux*|*hurd*|*msys*|*cygwin*|*sua*|*interix*) sys="gnu";;
        *bsd*|*darwin*) sys="bsd";;
        *sunos*|*solaris*|*indiana*|*illumos*|*smartos*) sys="sun";;
    esac
    [[ "${sys}" == "$1" ]];
}

So I can do stuff like:

if_nix gnu && alias ls='ls --color=auto' && export LS_COLORS="..."
if_nix bsd && export CLICOLORS=on && export LSCOLORS="..."
if_os linux && alias psg="ps -FA | grep" #alternative to pgrep
if_nix bsd && alias psg="ps -alwx | grep -i" #alternative to pgrep
if_os darwin && alias finder="open -R"
Keown answered 24/3, 2015 at 17:52 Comment(4)
BTW, these 9 lines work on any Bash running on most anything. No shellouts and works with almost any style of personal .bashrc (big nested if/case trees or lots of random aliases). IMO, beats the pants off every answer above it.Keown
So far, closest to complete for including Cygwin and other BSD (basically compilation of popular *NIX)Hay
Complete for userlands that are relevant today and run Bash. AIX/HP-UX/IRIX/OpenVMS users could chime in. The new Windows Subsystem for Linux runs a stock amd64 Ubuntu install so it should return true for both if_nix gnu & if_os linux.Keown
@Keown yes that's right, the win 10 bash subsystem outputs "linux-gnu" for echo $OSTYPE. To detect win 10 bash subsystem specifically, the only solution i've found was to check for "Microsoft" in /proc/sys/kernel/osreleaseSallet
C
9

You can use the following:

OS=$(uname -s)

then you can use OS variable in your script.

Cenac answered 23/11, 2017 at 11:42 Comment(3)
can you explain how uname -s is different than uname?Bibelot
@AlexanderMills -s, --kernel-name print the kernel nameCenac
@AlexanderMills on macos using bash man uname "If no options are specified, uname prints the operating system name as if the -s option had been specified."Postcard
P
8

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.

EDIT:

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.

Palila answered 12/3, 2009 at 19:15 Comment(0)
R
8

try this:

DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"
Rapeseed answered 8/11, 2018 at 10:4 Comment(5)
On macOS I get cat: /etc/*-release: No such file or directoryAirla
@Airla really, i'm getting the same: zsh: no matches found: /etc/*release -- this will work only for linux systems, I suppose...Rapeseed
This answer works for Linux, only, for sure. But other answers are capable of detecting Linux in opposition to other systems only. This basic discovery isn't helping at all for discovering particular Linux distribution is quite as essential as distinguishing between FreeBSD and Darwin.Bristol
okay, when I posted this comment, there was no need to perform this against multiple platforms, thus I tried to show how to see your Linux distro :)Rapeseed
This pipe symbol is used so beautifully!Braque
D
7

This should be safe to use on all distros.

$ cat /etc/*release

This produces something like this.

     DISTRIB_ID=LinuxMint
     DISTRIB_RELEASE=17
     DISTRIB_CODENAME=qiana
     DISTRIB_DESCRIPTION="Linux Mint 17 Qiana"
     NAME="Ubuntu"
     VERSION="14.04.1 LTS, Trusty Tahr"
     ID=ubuntu
     ID_LIKE=debian
     PRETTY_NAME="Ubuntu 14.04.1 LTS"
     VERSION_ID="14.04"
     HOME_URL="http://www.ubuntu.com/"
     SUPPORT_URL="http://help.ubuntu.com/"
     BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

Extract/assign to variables as you wish

Note: On some setups. This may also give you some errors that you can ignore.

     cat: /etc/upstream-release: Is a directory
Donica answered 21/8, 2014 at 1:10 Comment(9)
Note: on CentOS, this gives [user@host ~]$ cat /etc/*release CentOS release 6.4 (Final) CentOS release 6.4 (Final) CentOS release 6.4 (Final)Cineraria
Yes, the output I posted was an example, from one of my laptops, not static content you see everywhere.Donica
Just added that so nobody would think the result is always in the same form :)Cineraria
+1 I'm using set -e at the beginning of the script (Thus this solution isn't working doxer.org/linux-shell-centos-debian-ostype). And other solutions don't specifically CentOS. But I found this reference which proved this answer unix.stackexchange.com/a/92212Stave
does not work for Mac: cat: /etc/*release: No such file or directoryJoinville
Got another one: Debian 6 doesn't have /etc/debian_release, but /etc/debian_versionCineraria
The OP asked for OS such as OSX and Cygwin, this won't work on such OS. Answers resembling the env var $OSTYPE or $(uname -a) is the way it must be doneHay
Does not work on cygwin: cat: '/etc/*release': No such file or directoryAngkor
I clearly said distros. Mac OS X, cygwin are not distros. Mac OSX FreeBSD/BSD based, and cygwin is an environment. So I don't see why some are confused. And yes, works on debian too. The output may different per distro, but the information can be easily extracted.Donica
C
5

You can use following if clause and expand it as needed:

if [ "${OSTYPE//[0-9.]/}" == "darwin" ]
then
    aminute_ago="-v-1M"
elif  [ "${OSTYPE//[0-9.]/}" == "linux-gnu" ]
then
    aminute_ago="-d \"1 minute ago\""
fi
Contrariety answered 27/2, 2016 at 21:12 Comment(0)
H
3

I tend to keep my .bashrc and .bash_alias on a file share that all platforms can access. This is how I conquer the problem in my .bash_alias:

if [[ -f (name of share)/.bash_alias_$(uname) ]]; then
    . (name of share)/.bash_alias_$(uname)
fi

And I have for example a .bash_alias_Linux with:

alias ls='ls --color=auto'

This way I keep platform specific and portable code separate, you can do the same for .bashrc

Helpless answered 15/1, 2015 at 17:36 Comment(0)
J
3

I tried the above messages across a few Linux distros and found the following to work best for me. It’s a short, concise exact word answer that works for Bash on Windows as well.

OS=$(cat /etc/*release | grep ^NAME | tr -d 'NAME="') #$ echo $OS # Ubuntu
Jacquiline answered 8/3, 2017 at 16:25 Comment(7)
Whilst this code snippet is welcome, and may provide some help, it would be greatly improved if it included an explanation of how and why this solves the problem. Remember that you are answering the question for readers in the future, not just the person asking now! Please edit your answer to add explanation, and give an indication of what limitations and assumptions apply.Oleaceous
Seems nice and terse for most linux systems, but unfortunately this will result in an error on macOS. Perhaps this is more "detect the linux distribution flavor from BashAirla
@Airla OS=$( ([[ -f /etc/*release ]] && cat /etc/*release | grep ^NAME | tr -d 'NAME="') || echo "Unknown" ) this will work without throwing errors.Parliamentarianism
Actually, here is a correct way OS=$( $(compgen -G "/etc/*release" > /dev/null) && cat /etc/*release | grep ^NAME | tr -d 'NAME="') || $( echo "${OSTYPE//[0-9.]/}")Parliamentarianism
@Parliamentarianism I unfortunately still get errors running this on macOS.Airla
Just an update to @Kuzeko's command to stop it erroring.... OS=$( $(compgen -G "/etc/*release" > /dev/null) && cat /etc/*release | grep ^NAME | tr -d 'NAME="' || echo "${OSTYPE//[0-9.]/}")Contorted
Why compgen exactly ?Parliamentarianism
P
3

This checks a bunch of known files to identfy if the linux distro is Debian or Ubunu, then it defaults to the $OSTYPE variable.

os='Unknown'
unamestr="${OSTYPE//[0-9.]/}"
os=$( compgen -G "/etc/*release" > /dev/null  && cat /etc/*release | grep ^NAME | tr -d 'NAME="'  ||  echo "$unamestr")

echo "$os"
Parliamentarianism answered 2/10, 2018 at 19:12 Comment(0)
E
-1

Doing the following helped perform the check correctly for ubuntu:

if [[ "$OSTYPE" =~ ^linux ]]; then
    sudo apt-get install <some-package>
fi
Equisetum answered 21/8, 2013 at 1:53 Comment(2)
What about other Linux systems that don't use apt-get?Guyette
ubuntu is a distribution, not a operating system class.Matthews

© 2022 - 2024 — McMap. All rights reserved.