Ivo Karaneshev
Posted on October 4, 2023
Appending to PATH variable
In Linux, you have seen something like this
export SOME_ENV="..."
PATH="$SOME_ENV:$PATH"
which append the env variable value to PATH
.
It is really annoying to do this on the command line. So Linux guys suggest putting this in the ~/.bashrc
file.
Excellent.
But it can become a real mess quickly because there is all other important stuff in .bashrc
.
I don't feel it right to have everything bash-related bumped into one file.
Quick fix
So I decided to move all of my configured env variables to a separate file instead of messing things up in .bashrc
.
I called it .bash_envs
and placed it in my home directory (where .bashrc
is located).
I also separated bash functions and aliases into
.bash_functions
and.bash_aliases
respectively with the same idea in mind
In order to work properly, .bashrc
needs to know about and execute the .bash_envs
file.
So to accomplish this I wrote the following code in .bashrc
:
#Exported env definitions.
if [ -f ~/.bash_envs ]; then
. ~/.bash_envs
fi
Also .bash_envs
file needs to be executable so I typed a quick:
chmod +x .bash_envs
And the content of .bash_envs
includes something like this:
#!/bin/bash
...
# java
export JAVA_HOME="/usr/lib/jvm/java-21-openjdk-amd64"
PATH="$JAVA_HOME/bin:$PATH"
# pnpm
export PNPM_HOME="$HOME/.local/share/pnpm"
PATH="$PNPM_HOME:$PATH"
...
Perfect.
But to be honest, it is really annoying to type PATH=...
every time an env variable is exported.
So I came up with a better idea.
The improvement
If I could somehow store the required paths in something like an array, then join the items with a colon symbol (:
), and finally append it to PATH
?
Wait a second, there are arrays in bash
and I could do something like this:
path_envs=(
"$JAVA_HOME/bin"
"$PNPM_HOME"
...
)
But actually, I think it's better to append every item immediately after the env variable export
, because otherwise you can easily miss an item and you have to manually check if everything is as you expect.
Then the code should become something like this:
path_envs=() # defining an empty array
# java
export JAVA_HOME="/usr/lib/jvm/java-21-openjdk-amd64"
path_envs+=("$JAVA_HOME/bin") # appending java path to array
# pnpm
export PNPM_HOME="$HOME/.local/share/pnpm"
path_envs+=("$PNPM_HOME") # appending pnpm path to array
So far so good. But how to actually join items with a colon :
?
There are plenty of solutions but the easiest one I found was this:
PATH="$( IFS=":" ; echo "${path_envs[*]}" ):$PATH"
Don't worry I will explain step by step the above code snippet.
Explanation
$( Dollar Single Parentheses )
So the $( ... )
parentheses part means that everything inside will be executed in a subshell and the result will be returned as a string.
For example:
echo "Hello, my name is $( whoami )"
# => "Hello, my name is ivo"
Internal Field Separator (IFS)
The content inside the paratheses is more interesting. The first part (before the semicolon ;
) sets the special variable Internal Field Separator (IFS
) with a value of colon :
.
This in short means it treats :
as a separator between words/items in a string instead of whitespace which is the default.
More detailed information with examples about
IFS
can be found here.
The second part just prints the path_envs
array of its items separated by IFS
. One notable detail is that path_envs[*]
is used instead of path_env[@]
for expanding the array, because [*]
returns a single shell-word with all of the elements of the array separated by IFS
(as we need), while [@]
leads to each element of the array being treated as a separate shell-word.
As a result, the subshell should return something like:
/usr/lib/jvm/java-21-openjdk-amd64:/home/ivo/.local/share/pnpm...
Final result
All of that is finally concatenated with the old value of PATH
and simply that was the work we should do.
In the end, my .bash_envs
file looked something like this:
#!/bin/bash
path_envs=()
# java
export JAVA_HOME="/usr/lib/jvm/java-21-openjdk-amd64"
path_envs+=("$JAVA_HOME/bin")
# pnpm
export PNPM_HOME="$HOME/.local/share/pnpm"
path_envs+=("$PNPM_HOME")
# adding path_envs to PATH
PATH="$( IFS=":" ; echo "${path_envs[*]}" ):$PATH"
Posted on October 4, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 27, 2024