Reputation: 787
I would like to know about my shell version using a Linux command. I tried the following command, but it shows the type of the shell I am in.
Command:
echo $SHELL
Result:
/bin/bash
Upvotes: 64
Views: 127371
Reputation: 727
With these functions you can detect the path, name and version of the current shell.
The code was tested with bash, dash, busybox, mksh, ksh, zsh, bosh, osh, yash and posh. Tested under Windows, Linux, macOS and Android.
The complete file can be found here: https://github.com/micro5k/microg-unofficial-installer/blob/main/tools/bits-info.sh
get_shell_exe()
{
local _gse_shell_exe _gse_tmp_var
if _gse_shell_exe="$(readlink 2> /dev/null "/proc/${$}/exe")" && test -n "${_gse_shell_exe}"; then
# On Linux / Android / Windows (on Windows only some shells support it)
printf '%s\n' "${_gse_shell_exe}"
return 0
elif _gse_tmp_var="$(ps 2> /dev/null -p "${$}" -o 'comm=')" && test -n "${_gse_tmp_var}" && _gse_tmp_var="$(command 2> /dev/null -v "${_gse_tmp_var}")"; then
# On Linux / macOS
# shellcheck disable=SC2230 # Ignore: 'which' is non-standard
case "${_gse_tmp_var}" in *'/'* | *"\\"*) ;; *) _gse_tmp_var="$(which 2> /dev/null "${_gse_tmp_var}")" || return 3 ;; esac # We may not get the full path with "command -v" on osh
elif _gse_tmp_var="${BASH:-${SHELL-}}" && test -n "${_gse_tmp_var}"; then
if test "${_gse_tmp_var}" = '/bin/sh' && test "$(uname 2> /dev/null || :)" = 'Windows_NT'; then _gse_tmp_var="$(command 2> /dev/null -v 'busybox')" || return 2; fi
if test ! -e "${_gse_tmp_var}" && test -e "${_gse_tmp_var}.exe"; then _gse_tmp_var="${_gse_tmp_var}.exe"; fi # Special fix for broken versions of Bash under Windows
else
return 1
fi
_gse_shell_exe="$(readlink 2> /dev/null -f "${_gse_tmp_var}" || realpath 2> /dev/null "${_gse_tmp_var}")" || _gse_shell_exe="${_gse_tmp_var}"
printf '%s\n' "${_gse_shell_exe}"
return 0
}
get_shell_info()
{
local _shell_use_ver_opt _shell_exe _shell_name _shell_version _shell_is_ksh _tmp_var
_shell_use_ver_opt='false'
_shell_exe="${1-}"
_shell_name=''
_shell_version=''
_shell_is_ksh='false'
if test -n "${_shell_exe}"; then
_shell_name="$(basename "${_shell_exe}" | tr -d ' ')" || _shell_name=''
_shell_name="${_shell_name%'.exe'}" # For shells under Windows
fi
if test -z "${_shell_name}"; then
printf '%s\n' 'not-found unknown'
return 1
fi
case "${_shell_exe}" in
*'/bosh/'*'/sh') _shell_name='bosh' ;;
*'/oils-for-unix' | *'/oil.ovm') _shell_name='osh' ;;
*) ;;
esac
case "${_shell_name}" in
*'ksh'*) _shell_is_ksh='true' ;;
'zsh' | 'bosh' | 'osh' | 'yash' | 'tcsh' | 'fish') _shell_use_ver_opt='true' ;;
*) ;;
esac
# Various shells doesn't support '--version' and in addition some bugged versions of BusyBox open
# an interactive shell when the '--version' option is used, so use it only when really needed.
if test "${_shell_use_ver_opt}" = 'true' && _shell_version="$("${_shell_exe}" 2>&1 --version)" && test -n "${_shell_version}"; then
:
else
# NOTE: "sh --help" of BusyBox may return failure but still print the correct output although it may be printed to STDERR
_shell_version="$("${_shell_exe}" 2> /dev/null -Wversion || "${_shell_exe}" 2>&1 --help || :)"
fi
_shell_version="$(printf '%s\n' "${_shell_version}" | head -n 1)" || return "${?}"
case "${_shell_version}" in
'' | *'Usage'* | *'invalid option'* | *'unrecognized option'* | *[Uu]'nknown option'* | *[Ii]'llegal option'* | *'not an option'* | *'bad option'* | *'command not found'* | *'No such file or directory'*)
if test "${_shell_is_ksh}" = 'true' && test -n "${KSH_VERSION-}" && _shell_version="${KSH_VERSION}"; then
: # For ksh (include also variants like mksh)
elif test "${_shell_name}" = 'dash' && test -n "${DASH_VERSION-}" && _shell_version="${DASH_VERSION}"; then
: # For dash (possibly supported in the future)
elif test "${_shell_name}" = 'dash' && command 1> /dev/null 2>&1 -v 'dpkg' && _shell_version="$(dpkg -s 'dash' | grep -m 1 -F -e 'Version:' | cut -d ':' -f '2-' -s)" && test -n "${_shell_version}"; then
: # For dash under Linux
elif test "${_shell_name}" = 'dash' && command 1> /dev/null 2>&1 -v 'brew' && _shell_version="$(NO_COLOR=1 brew 2> /dev/null info 'dash' | head -n 1 | grep -m 1 -F -e 'dash:' | cut -d ':' -f '2-' -s | cut -d ',' -f '1')" && test -n "${_shell_version}"; then
: # For dash under macOS
_shell_version="${_shell_version# }"
_shell_version="${_shell_version#stable }"
elif test "${_shell_name}" = 'dash' && command 1> /dev/null 2>&1 -v 'apt-cache' && _shell_version="$(apt-cache policy 'dash' | grep -m 1 -F -e 'Installed:' | cut -d ':' -f '2-' -s)" && test -n "${_shell_version}"; then
: # For dash under Linux (it is slow)
elif test "${_shell_name}" = 'posh' && test -n "${POSH_VERSION-}" && _shell_version="${POSH_VERSION}"; then
: # For posh
elif _shell_version="$(\eval 2> /dev/null ' \echo "${.sh.version-}" ' || :)" && test -n "${_shell_version}"; then
: # Fallback for old ksh and bosh
elif test -n "${version-}" && _shell_version="${version}"; then
: # Fallback for tcsh and fish (NOTE: although this variable would show the version unfortunately the code cannot be run on tcsh and fish due to syntax difference)
else
_shell_version=''
fi
;;
*) ;;
esac
case "${_shell_version}" in
'BusyBox '*) _shell_name='busybox' ;;
*' bash,'*) _shell_name='bash' ;; # Sometimes "sh" isn't just a symlink to "bash" but it is really called "sh" so we have to correct this
*) ;;
esac
_shell_version="${_shell_version#*[Vv]ersion }"
case "${_shell_name}" in
'busybox') _shell_version="${_shell_version#BusyBox}" ;;
'osh') _shell_version="$(printf '%s\n' "${_shell_version#Oils}" | cut -f '1')" ;;
'mksh') _shell_version="${_shell_version#*MIRBSD KSH}" ;;
'') ;;
*) _shell_version="${_shell_version#"${_shell_name}"}" ;;
esac
_shell_version="${_shell_version# }"
_shell_version="${_shell_version#v}"
printf '%s %s\n' "${_shell_name:-unknown}" "${_shell_version:-unknown}"
}
shell_exe="$(get_shell_exe)"
echo "${shell_exe}"
get_shell_info "${shell_exe}"
Upvotes: 0
Reputation: 19
Just use command
echo $BASH_VERSION
It must give you the version of shell. BASH_VERSION is the environment variable which contains version of shell.
Upvotes: 0
Reputation: 2558
There is a case when your shell does not have a command line parameter to determine the version directly. This case is Bourne shell. For Bourne shell I would recommend to use a script: https://www.in-ulm.de/~mascheck/various/whatshell/whatshell.sh. The script is pretty small so that it is not a big trouble to review it and understand how it is working. I have tested this script inside different shells on Linux and Solaris and it always gave the shell version for me.
Some examples:
Ubuntu 18.04
$ sh -c './whatshell.sh'
ash (Busybox 1.x)
$ bash -c './whatshell.sh'
bash 4.4.19(1)-release
CentOS 4
$sh -c './whatshell.sh'
bash 3.00.15(1)-release
Solaris 10
~> sh -c './whatshell.sh'
ksh88 Version (..-)11/16/88i (posix octal base)
~> bash -c './whatshell.sh'
bash 4.1.7(3)-release
~> csh -c './whatshell.sh'
SVR4 Bourne shell (SunOS 5 variant)
AIX 6.1
~> sh -c './whatshell.sh'
ksh88 Version (..-)11/16/88f
~> bash -c './whatshell.sh'
bash 4.2.0(1)-release
This is also answers for the question Bourne shell version which was marked as off topic.
Upvotes: 10
Reputation: 263257
It depends on whether you want to know the version of your default login shell, or the version of the shell you're currently running. They're not necessarily the same.
For your default login shell, as the accepted answer says, $SHELL --version
is likely to work. Most (but not all) shells accept a --version
option. (dash
does not.) And this assumes that the value of $SHELL
hasn't been changed (there can be valid reasons to do so).
For the shell you're currently running, if it happens to be bash
you can type:
echo $BASH_VERSION
For tcsh
:
echo $version
For zsh
:
echo $ZSH_VERSION
echo $ZSH_PATCHLEVEL # shows more detailed information
For ksh
:
echo $KSH_VERSION
For fish
:
echo $version
Again, this assumes that the relevant variable hasn't been modified (there's rarely any non-malicious reason to change it).
Bash in particular has an array variable $BASH_VERSINFO
that gives more information in a form that's easier to process programmatically. Printing $BASH_VERSINFO
only prints the first element; to print all elements:
echo "${BASH_VERSINFO[@]}"
Upvotes: 23
Reputation: 4089
This will do it:
$SHELL --version
In my case, the output is:
zsh 5.0.2 (x86_64-pc-linux-gnu)
Upvotes: 71