skip to Main Content

Many shell scripts, including the bash profile, are simply lists of environment variable settings. One such script on Debian is /etc/os-release which looks like this:

PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

The VERSION_CODENAME is particularly useful for adding to apt sources (/etc/apt/sources.list) for, say, Steam to work on ChromeOS. Note that most instructions hard-code this value which can cause compatibility problems.

So my question then is how to echo an env var such as VERSION_CODENAME from a file such as /etc/os-release without using source? That’s key because I don’t want to clutter up my environment variables with these for a one-time use.

Here’s what I know I can do now but it leaves the variables in my current environment which is undesirable:

source /etc/os-release && echo "deb http://httpredir.debian.org/debian/ $VERSION_CODENAME main contrib non-free | sudo tee -a /etc/apt/sources.list"

I thought perhaps there is a way to start a new (temporary) bash process and load the variables into that environment. I haven’t been able to figure that out without an actual shell script.

4

Answers


  1. 4 different answer here…

    Sorry, but there is more than one way;). You may found a lot of other ways, but there are the most appropriate (quickness, efficience, footprint, readability…).

    1. import through sed to populate associative arrray:

    declare -A IMPORTED="($(sed < /etc/os-release 's/^([^=]+)=/[1]=/'))"
    

    Then

    echo ${IMPORTED[VERSION_CODENAME]}
    buster
    

    2. extract required field (by using sed again)

    AltVersionCodename=$(sed </etc/os-release -ne 's/^VERSION_CODENAME=//p')
    echo $AltVersionCodename
    buster
    

    3. parenthesis to drop down to subshell using his own environment

    ( . /etc/os-release ; echo $VERSION_CODENAME )
    buster
    
    echo $VERSION_CODENAME
     
    

    Current environment don’t know about $VERSION_CODENAME

    4. reading variable file in pure bash, without forks

    As we are working on a small file, we could use loop to read the file until required info is found:

    while IFS== read varname value;do
        [ "$varname" = "VERSION_CODENAME" ] &&
            ImportedVersionCodename=$value && break
    done </etc/os-release
    echo $ImportedVersionCodename 
    buster
    
    Login or Signup to reply.
  2. I thought perhaps there is a way to start a new (temporary) bash process and load the variables into that environment.

    That’s what using parenthesis to create a subshell does.

    (
      . /etc/os-release
      echo "deb http://httpredir.debian.org/debian/ $VERSION_CODENAME main contrib non-free" 
      | sudo tee -a /etc/apt/sources.list
    )
    

    …as soon as the ) is hit, your variables are removed, as the subshell they were loaded into exits.

    Login or Signup to reply.
  3. Or using read and printf like this:

    while read line; do
        name=${line%%=*}
        data=${line#*=}
        printf -v $name "${data//"}"
    done < vars
    
    Login or Signup to reply.
  4. The next function only sources the line with the key (value in single quotes).

    my_set() {
       configfile="$1"
       key="$2"
       print -v "$key" $(sed -n "s/^${key}=//p" "${configfile}")
    }
    my_set /etc/os-release VERSION_CODENAME
    echo "deb http://httpredir.debian.org/debian/ $VERSION_CODENAME main.."
    

    When you don’t need the var in the environment, use

    my_set2() {
       configfile="$1"
       key="$2"
       sed -n "s/^${key}=//p" "${configfile}"
    }
    
    echo "deb http://httpredir.debian.org/debian/ $(my_set2 /etc/os-release VERSION_CODENAME) main.."
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search