When I cat /etc/os-release I get the following:

PRETTY_NAME="Kali GNU/Linux Rolling"
NAME="Kali GNU/Linux"

How would I grab kali from ID= in bash? How would I grab 2018.1 from VERSION= in bash?

  • Why did you think they would work? – jesse_b Mar 22 '18 at 12:01

you can source the file and use var's value

. /etc/os-release
echo $ID

or try with awk

awk -F= '$1=="ID" { print $2 ;}' /etc/os-release


  • -F= tell awk to use = as separator
  • $1=="ID" filter on ID
  • { print $2 ;} print value
  • 1
    As JdeBP says, and thedailywtf.com points out regularly, source-ing files is a risky way to go about your day. – Carl Witthoft Aug 24 '20 at 12:46
  • In debian like the value not contains quotes. – e-info128 Jul 1 at 17:30

Sourcing and awk are poor ideas

Sourcing these sorts of files with a shell script interpreter is a poor idea, as it introduces yet another place where the malicious can hide shell script to be executed with superuser permissions, or can introduce things like an override for variables like PATH, LANG, and LD_LIBRARY_PATH.

% cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch with subversive \$PATH)"
NAME="Debian GNU/Linux"
VERSION="9 (stretch)"
echo 1>&2 'install -m 0644 /etc/shadow /home/malefactor/etc/ 2>/dev/null'
% ( source /etc/os-release ; command -v start-stop-daemon ; )
install -m 0644 /etc/shadow /home/malefactor/etc/ 2>/dev/null

Sourcing actually violates one of the defined semantics for /etc/os-release, which is that (to quote its manual) "variable expansion is explicitly not supported".

Similarly, awk as supplied in Archemar's answer does not correctly handle quoting; and any value can be quoted. Notice how Archemar's answer does not address the VERSION value in the question, which the given awk script does not provide the correct value for, because it erroneously retains the quoting and does not handle escape sequences.

% awk -F= '$1=="VERSION" { print $2 ;}' /etc/os-release
"9 (stretch)"      
% awk -F= '$1=="PRETTY_NAME" { print $2 ;}' /etc/os-release
"Debian GNU/Linux 9 (stretch with subversive \$PATH)"

/etc/os-release is actually permitted a fairly broad latitude in quoting, and also requires that escape sequences be processed properly. awk is not really the right tool for the job at all, here.

There are other, subtler, problems such as leakage of already set variables into the results if the actual key sought is missing from the file.

% ( source /etc/os-release ; echo $LANG ; )
install -m 0644 /etc/shadow /home/malefactor/etc/ 2>/dev/null

There's also the fact that if ID or PRETTY_NAME are missing, they are defined as having default values. And on top of that, there's the fallback to /usr/lib/os-release to deal with.

Learning from other people

Files that contain key-equals-value assignments, with sh-style quoting, escaping, and commentary, are a fairly common thing. Some programming languages have library functions for dealing with them directly. The lesson of OpenBSD's rules shift on /etc/rc.conf in OpenBSD 5.6 is that it is the wiser course to use such library functions, if available, or dedicated tools that have nowhere near the capabilities of a full shell interpreter, for processing such files.

From shell scripts, I for one use a tool named read-conf to process such files:

% read_os() {
    if test -r /etc/os-release
        clearenv setenv "$1" "$2" read-conf /etc/os-release printenv "$1"
        clearenv setenv "$1" "$2" read-conf /usr/lib/os-release printenv "$1"
% read_os ID linux
% read_os VERSION
9 (stretch)
% read_os PRETTY_NAME Linux
Debian GNU/Linux 9 (stretch with subversive $PATH)
% read_os PATH
% read_os LANG

The aforegiven relies on setenv, read-conf, and printenv commands being built-in commands in the nosh toolset, so that clearenv, setenv, and read-conf each find the next command in the chain without using the PATH environment variable at all. (Before I added the built-in printenv, the slightly longer original one-liners made careful use of "`command -v printenv`" to avoid searching for printenv after the infected configuration file had maliciously set an altered PATH, and after clearenv had wiped that variable from the environment.)

Further reading

  • Theo de Raadt et al. (2014-11-01). OpenBSD 5.6 Changelog. OpenBSD.
  • Jonathan de Boyne Pollard (2018). "read-conf". Manual. nosh toolset. Softwares.
  • Jonathan de Boyne Pollard (2018). "clearenv". Manual. nosh toolset. Softwares.
  • Jonathan de Boyne Pollard (2018). "setenv". Manual. nosh toolset. Softwares.
  • Jonathan de Boyne Pollard (2018). "printenv". Manual. nosh toolset. Softwares.
  • Guilty !! I would have tought that only root can write /etc/os-release and root have no need to deploy malevolent script. Thoses seems fine manual you speak about ... – Archemar Mar 31 '18 at 16:38
ID=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"')
VERSION=$(grep -oP '(?<=^VERSION_ID=).+' /etc/os-release | tr -d '"')

For the explanation see the other two great answers:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.