In this post, I will explain how to import custom environment variables from a JSON file. I will also improve the shortcuts we create in the previous posts.
Requirements
- Linux (I'm using Elementary OS, a Ubuntu-based distro, try it!)
- VS Code. If you don't want to use it, change all the
code
commands in the bash code for your text editor. Alternatives: gedit or gnome-text-editor. - fzf command-line fuzzy finder
Notes
- Remember to add execution permissions to the scripts through
chmod +x
- Profile script:
$HOME/.bashrc
for bash terminal and$HOME/.zshrc
for zsh
Variables
Let's say I want to define some variables as:
- my local github repositories path
- my documents path
- path to a specific file, in this case, the path to a JSON file containing some bookmarks I have, check my previous post
By defining them in the profile script as:
# add this at the end of your profile
localRepos="$HOME/repos"
localDocuments="$HOME/Documents"
bookmarksFile="$localRepos/cangulo-blog/cangulo.github.io/blog/posts/bash/3-setup-custom-env-variables/code/4-bookmarks.json"
We can use them during the terminal session.
Let's append the next function and aliases at the bash profile. Please note those are using the variables defined before.
# add this at the end of your profile, after the variables declaration
alias goToRepos="cd $localRepos"
alias goToDocs="cd $localDocuments"
listBookmarks() {
local pathSelected=$(cat $bookmarksFile |
jq -r '.[]' |
fzf)
if [[ -n "$pathSelected" ]]; then
cd $pathSelected
else
echo "no bookmark selected"
fi
}
Now, we can use them after opening the Terminal.
Behavior vs Configuration
In a previous post, the listBookmarks
function has the bookmarksFile
hardcoded.
listBookmarks() {
local bookmarksFile=./bookmarks.json
As you see, its value refers to the bookmarks.json
location. What happens if we move that file to another folder? We would have to update the function. For one variable this doesn't seem to be a problem, right? But what if it is hardcoded in more functions? we would have to update them all, that is not extensible!
Let's define two terms here:
- Behavior: Functions implementation.
- Configuration: Input parameters that the function relies on. In this case,
bookmarksFile
.
By setting all the parameters outside the functions, we are creating a central place for the configuration.
localRepos="$HOME/repos"
localDocuments="$HOME/Documents"
bookmarksFile="$localRepos/cangulo-blog/cangulo.github.io/blog/posts/bash/3-setup-custom-env-variables/code/4-bookmarks.json"
And by calling those from the functions:
listBookmarks() {
local pathSelected=$(cat $bookmarksFile |
We are decoupling configuration from behavior. If we want to migrate or share this setup, we won't need to look at the function implementations, we would only need to update the parameters.
One extra mile: Define the parameters as JSON
Let's migrate the variables to a JSON file as follows. Please note all the paths are now absolute.
{
"localRepos": "/home/cangulo/repos",
"localDocuments": "/home/cangulo/Documents",
"bookmarksFile": "/home/cangulo/repos/cangulo-blog/cangulo.github.io/blog/posts/bash/3-setup-custom-env-variables/code/4-bookmarks.json"
}
To set the JSON keys as the parameters name we have to:
- Define the json file path. We will consider those as the main settings.
- Use the
jq
command to retrieve the keys and values. - Use the
eval
command to execute thekey=value
for each one.
Next is the solution, replace the variables declaration in your profile for this.
settingsFile="/home/cangulo/repos/cangulo-blog/cangulo.github.io/blog/posts/bash/3-setup-custom-env-variables/code/3-vars.json"
eval "$(jq -r 'to_entries | .[] | .key + "=" + (.value | @sh)' <$settingsFile)"
In case you want to go into the solution details. Click here.
References:
jq -r 'to_entries'
structures the json as key/value pair array:
jq -r 'to_entries | .[]'
prepare the array items for the iteration:
jq -r 'to_entries | .[] | .key + "=" + .value'
build the key=value
expressions
jq -r 'to_entries | .[] | .key + "=" + (.value | @sh)'
format the expression
Nothing more for Today! Do you think this is a good approach? How would you do it? Let me know in the comments below.
About me
I'm a Software Engineer with experience as Developer and DevOps. The technologies I have worked with are DotNet, Terraform and AWS. For the last one, I have the Developer Associate certification. I define myself as a challenge-seeker person and team player. I simply give it all to deliver high-quality solutions. On the other hand, I like to analyze and improve processes, promote productivity and document implementations (yes, I'm a developer that likes to document ๐งโ๐ป).
You can check my experience here.
Personal Blog - cangulo.github.io
GitHub - Carlos Angulo Mascarell - cangulo
LinkedIn - Carlos Angulo Mascarell
Twitter - @AnguloMascarell