The script should be able to detect the operating system that is running.
The alternatives OS is Arch Linux, Centos and Ubuntu.
os=$(uname)
if [ "$os" == "Arch" ]; then
echo "Arch Linux detected"
elif [ "$os" == "CentOS" ]; then
echo "CentOS detected"
elif [ "$os" == "Ubuntu" ]; then
echo "Ubuntu detected"
else
echo "Unknown OS detected"
fi```
Output: Unknown OS detected
I tried doing this:
\`del1()
{
os=$(cat /etc/os-release | grep "PRETTY_NAME")
}
del1
echo "The operating system is: $os"\`
The output: PRETTY_NAME="Ubuntu 20.04.2 LTS"
But I want to check between Centos, Arch Linux and Ubuntu.
Any suggestions?
The uname command will always return Linux when running on Linux, so of course that's never going to work.
Using /etc/os-release is probably the best solution, but don't grep it for information; the file is a collection of shell variables that you can source with the . command, so you can write something like this:
#!/bin/sh
. /etc/os-release
case $ID in
ubuntu) echo "This is Ubuntu!"
;;
arch) echo "This is Arch Linux!"
;;
centos) echo "This is CentOS!"
;;
*) echo "This is an unknown distribution."
;;
esac
You can use the grep command to filter the output of the cat /etc/os-release command for specific strings that indicate the operating system.
For example, you could use the following command to check for Ubuntu:
os=$(cat /etc/os-release | grep -o "Ubuntu")
You could then use an if statement to check if the variable os equals to Ubuntu:
if [ "$os" == "Ubuntu" ]; then
echo "Ubuntu detected"
else
echo "Not Ubuntu detected"
fi
You can do the same to check for Arch Linux:
os=$(cat /etc/os-release | grep -o "Arch")
And for Centos:
os=$(cat /etc/os-release | grep -o "CentOS")
You can also use cat /etc/*-release instead of cat /etc/os-release for more general detection of the OS.
You can also use lsb_release -a command to get more details about the distribution and version of the OS.
os=$(lsb_release -a | grep -o "Ubuntu")
You can then create a function that check for each os one by one and print the output accordingly.
check_os(){
os=$(cat /etc/os-release | grep -o "Ubuntu")
if [ "$os" == "Ubuntu" ]; then
echo "Ubuntu detected"
else
os=$(cat /etc/os-release | grep -o "Arch")
if [ "$os" == "Arch" ]; then
echo "Arch Linux detected"
else
os=$(cat /etc/os-release | grep -o "CentOS")
if [ "$os" == "CentOS" ]; then
echo "CentOS detected"
else
echo "Unknown OS detected"
fi
fi
fi
}
check_os
Please note that this approach might not be 100% accurate and it is better to use the appropriate package manager commands to check the OS version and distribution.
If you just need to check the name of the OS, you can try;
source /etc/os-release
echo "The operating system is: $NAME"
I'm trying to add a conditional to my .zshrc file that will initialize some config stuff that I only want to happen if I'm in Windows Subsystem for Linux. I tried this but no luck:
if [ "$('cmd.exe /c "systeminfo" | grep "^OS Name"')" =~ "Windows" ]; then
echo "windows baby!"
fi
Which gives:
no such file or directory: cmd.exe /c "systeminfo" | grep "^OS Name"
...but that command works if I type it directly in the shell.
Any ideas?
Using uname -r does the trick
According to https://github.com/microsoft/WSL/issues/423#issuecomment-608236476, if you use
uname -r | sed -n 's/.*\( *Microsoft *\).*/\1/ip'
You'll get output as "Microsoft" in case it is WSL. Otherwise, you should get no output.
So you can use something like
if [ $(uname -r | sed -n 's/.*\( *Microsoft *\).*/\1/ip') ];
then
echo "This is Windows WSL baby!"
else
echo "Not Windows"
fi
How do I perform the mount only if it has not already been mounted?
This is on OS X 10.9 and this is what I have currently:
#!/bin/bash
# Local mount point
LOCALMOUNTPOINT="/folder/share"
# Perform the mount if it does not already exist
if ...
then
/sbin/mount -t smbfs //user:password#serveraddress/share $LOCALMOUNTPOINT
else
echo "Already mounted"
fi
While #hd1's answer gives you whether the file exists, it does not necessary mean that the directory is mounted or not. It is possible that the file happen to exist if you use this script for different machines or use different mount points. I would suggest this
LOCALMOUNTPOINT="/folder/share"
if mount | grep "on $LOCALMOUNTPOINT" > /dev/null; then
echo "mounted"
else
echo "not mounted"
fi
Note that I include "on" in grep statement based on what mount command outputs in my machine. You said you use MacOS so it should work, but depending on what mount command outputs, you may need to modify the code above.
This is what I use in my shell scripts on OS X 10.7.5
df | awk '{print $6}' | grep -Ex "/Volumes/myvolume"
For OS X 10.10 Yosemite I have to change to:
df | awk '{print $9}' | grep -Ex "/Volumes/myvolume"
For me from this solution in stackoverflow_QA_Check if a directory exists in a shell script
[ -d /Volumes/ ] && echo "Already mounted /Volumes/ in OS X" || echo "Not mounted"
to use that
# 2 lines
$LOCALMOUNTPOINT="/folder/share" ;
[ -d $LOCALMOUNTPOINT ] && echo "Already mounted $LOCALMOUNTPOINT in OS X" || /sbin/mount -t smbfs //user:password#serveraddress/share $LOCALMOUNTPOINT
Here is Stackoverflow_QA_how-can-i-mount-an-smb-share-from-the-command-line
additional link about smb which I don't know well
# Here is my solution
$LOCALMOUNTPOINT="/folder/share" ;
[ ! -d $LOCALMOUNTPOINT ] && mkdir $LOCALMOUNTPOINT && /sbin/mount -t smbfs //user:password#serveraddress/share $LOCALMOUNTPOINT || echo already mounted $LOCALMOUNTPOINT
I have to make new folder for my SMOOTH use before mounting that.
so I added mkdir $LOCALMOUNTPOINT
Thank you I learned a lot with this case.
Have A nice day!!! ;)
I want to set up some environment variable in the makefile only if the system is Ubuntu 11.04 or higher.
I am able to extract the OS name using
cat /etc/lsb-release | grep DISTRIB_ID| cut -d "=" -f 2
and version number using
cat /etc/lsb-release | grep DISTRIB_RELEASE| cut -d "=" -f 2
So in my makefile I do
OSNAME := $(shell cat /etc/lsb-release | grep DISTRIB_ID| cut -d "=" -f 2)
I get the error that /etc/lsb-release not found.
My approach 2 was to use lsb_release -si and -sr , although these commands works fine in the terminal, the below prints that Ubuntu not found in a Makefile
ifeq ($(shell lsb_release -si),Ubuntu)
$(info YES UBUNTU DETECTED)
else
$(info NO UBUNTU DETECTED)
endif
What am I doing wrong is there a clean way conditionally setup environment variables is the system is Ubuntu 11.04 or higher?
Try this
if [ -f /etc/lsb-release ]; then
. /etc/lsb-release
OS=$DISTRIB_ID
VER=$DISTRIB_RELEASE
else
OS=$(uname -s)
VER=$(uname -r)
fi
echo $OS
echo $VER
Or like this sort command
OS=$(lsb_release -si)
ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/')
VER=$(lsb_release -sr)
echo $OS
echo $VER
echo $ARCH
Or in makefile you require like this
UNAME_OS := $(shell lsb_release -si)
ifeq ($(UNAME_OS),Ubuntu)
$(info YES UBUNTU DETECTED)
else
$(info NO UBUNTU DETECTED)
endif
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?
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
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.
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.
$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
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!)
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
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
uname
or
uname -a
if you want more information
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.
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 :)
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"
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]
...
You can use the following:
OS=$(uname -s)
then you can use OS variable in your script.
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.
try this:
DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"
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
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
This is what I use if anyone is interested in detecting WSL vs WSL verion 2 as well.
#!/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};
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
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
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"
Doing the following helped perform the check correctly for ubuntu:
if [[ "$OSTYPE" =~ ^linux ]]; then
sudo apt-get install <some-package>
fi