Tired of having to manually copy your favorite Bash aliases and functions to every new server or Linux distro? I solved the sync problem! I show you how to set up your Bash profile to pull configurations from a centralized Git repository. I implement some logic so those same configurations work flawlessly across various distros and machines. The payoff? A perfectly reusable and synchronized Bash environment that's always up-to-date with every commit.
Set up a Git Repo
Create or login to github.com, go to Repositories and create your GitHub repo. In this example, we'll create a repo called shell.
On your machine, create a /repos directory in /var directory and change directory into that path. If you want to use another filename or location for your Repos dir, change to that path.
mkdir /var/repos && cd /var/repos
Also make sure your user has permissions on your repos directory.
sudo chown -R $USER:$USER /var/repos
Inside your Repos directory, git clone the bash repo you made on GitHub.
git clone https://github.com/<username>/bash.git
Set up your .bash_profile
Inside your user's .bash_profile (located in your home directory), add the following lines:
if [[ -f "${HOME}/.bashrc" ]]; then
source "${HOME}/.bashrc"
fi
Next, inside your user's .bashrc (also located in your home directory), add the following lines:
export REPOS_DIR="/var/repos"
export WORK_REPOS_DIR="${REPOS_DIR}/work"
export MY_REPOS_DIR="${REPOS_DIR}/personal"
export SHELL_UTILS_DIR="${MY_REPOS_DIR}/shell"
if [[ -f "${SHELL_UTILS_DIR}/index.sh" ]]; then
source "${SHELL_UTILS_DIR}/index.sh"
fi
This file will allow you to use two environment variables across any shell you start, but it will also load all your configs from index.sh, in which we will add and create all kinds of shell customizations.
Set up bash configurations & functions
In the shell repo, create file called index.sh, aliases.sh and prompt.sh. Also create a directory functions with and an additional index.sh.
Inside your root index.sh, add a shebang and references to the bash aliases, bash functions and prompt file:
if [ -f ${SHELL_UTILS_DIR}/aliases.sh ]; then
. ${SHELL_UTILS_DIR}/aliases.sh
fi
if [ -f ${SHELL_UTILS_DIR}/functions/index.sh ]; then
. ${SHELL_UTILS_DIR}/functions/index.sh
fi
# Zsh exclusives
if [ -n "$ZSH_VERSION" ]; then
# Oh my Zsh
export ZSH="${HOME}/.oh-my-zsh"
ZSH_THEME="robbyrussell"
source ${ZSH}/oh-my-zsh.sh
# Prompt string
precmd() {
print ""
}
fi
# Bash exclusives
if [ -n "$BASH_VERSION" ]; then
if [ -f ${SHELL_UTILS_DIR}/prompt.sh ]; then
. ${SHELL_UTILS_DIR}/prompt.sh
fi
fi
These lines reference all the bash configs, aliases and functions we want to add to our bash environment on every machine. And the bashrc.sh itself will be loaded in the .bashrc we adapted earlier.
If you want, you can set different locations for your repos directory on each machine. The reusability of
SHELL_UTILS_REPOis practical because you may want to set aliases to files or scripts inside your bash repo. They will work on each machine, if you reuse${SHELL_UTILS_REPO}in your aliases or scripts.
Inside aliases.sh, add useful aliases you want to reuse on every machine, e.g.
alias my-ip="echo $(curl -s ifconfig.me)";
This example is a command to print your IP address.
Inside functions.sh, add useful functions you want to reuse on every machine, e.g.
get_os() {
uname -s
}
get_cores() {
if [[ "$(uname -s)" == "Darwin" ]]; then
echo $(sysctl -n hw.ncpu)
else
echo $(nproc || grep -c ^processor /proc/cpuinfo)
fi
}
This example is a function that will print your current Linux distro (the command is not available on macOS).
Inside prompt.sh, customize your command prompt, e.g.
#!/bin/bash
#
# Bash prompt string
# Get current git branch
git_branch() {
local branch
branch=$(git branch --show-current 2>/dev/null)
[ -n "$branch" ] && echo " (${branch})"
}
# Set colors
set_yellow='\[\e[33m\]'
set_green='\[\e[32m\]'
set_red='\[\e[1;31m\]'
reset='\[\e[0m\]'
ps_path="${set_yellow}\w${reset}"
ps_git_branch="${set_green}\$(git_branch)${reset}"
ps_symbol="${set_red}\$${reset}"
# \u: the username of the current user.
# \h: the hostname up to the first dot (.) in the Fully-Qualified Domain Name.
# \W: the basename of the current working directory, with $HOME abbreviated with a tilde (~).
PS0='\n'
PS1="\n${ps_path}${ps_git_branch} ${ps_symbol} "
PS2=''
This example will adapt your command prompt.
Set an update function that can be executed on any Linux distro
We create a bash function called “update” that we can execute on any Linux distro to update our machine.
Inside your bash_functions.sh, add the following lines:
update() {
if [[ $(get_os) == *"Ubuntu"* ]]; then
sudo echo -e "updating available software\n----"
sudo apt-get update;
echo -e "\nupgrading software\n----"
sudo apt-get upgrade;
echo -e "\nremoving obsolete dependency software\n----"
sudo apt-get autoremove --purge;
echo -e "\nremoving software in local cache\n----"
sudo apt-get clean;
echo "Done"
elif [[ $(get_os) == *"Fedora"* ]]; then
sudo echo -e "updating available software\n----"
sudo dnf upgrade
echo -e "\nremoving obsolete dependency software\n----"
sudo dnf autoremove
echo -e "\nremoving software in local cache\n----"
sudo dnf clean all
echo "Done"
fi
}
In this example, we set an update function that uses the get_OS function to match it with a distro. In case of Ubuntu, we run updates and clean after with apt-get. In case of Fedora, we run updates and clean after with dnf. This can be extended with other distros.
Set a cleanup function that can be executed on each machine
Create a clean.sh file in your bash repo.
touch ${SHELL_UTILS_REPO}/clean.sh
Inside clean.sh, add the following lines:
#!/bin/bash
#
# Tidy your machine
# General file paths
file_paths=("${HOME}/Desktop/*" "${HOME}/Downloads/*" "${HOME}/Pictures/Screen*")
# Linux-specific file paths
if [ $(uname) == "Linux" ]; then
file_paths+=("${HOME}/.local/share/Trash/files/*")
fi
# MacOS-specific file paths
if [ $(uname) == "Darwin" ]; then
file_paths+=("${HOME}/.Trash/*")
file_paths+=("${HOME}/Library/Mobile\ Documents/com\~apple\~CloudDocs/.Trash/*")
fi
# Remove file paths
for file_path in ${file_paths[@]}; do
rm -rf "${file_path}"
done
exit 0
In this example, we create an array of general file paths that need to be cleaned. Then we append file paths to that array, depending on the type of OS. Finally, we iterate over the array and remove (recursively and forced) all the files on that file path. Notice the * after each file path, which makes sure only the children of that directory are deleted.

Top comments (0)