Hassan Ali

@hassanhelfi

Learn How to Manage Dotfiles

I recently got a new laptop and a coworker of mine suggested I start automating my setup configurations. The goal is to allow me bootstrap and replicate my configuration preferences on different machines almost instantly. One item leading the todo’s list is the management of dotfiles. Today I will share with you how you can harness the power of the Unix shell to create a script that you can use to manage your dotfiles between different machines.

Dotfiles are used to customize Unix-like systems. The neat thing about them is that they could be modified to suit your own preferences. Examples include .gitconfig, .bash_profile and .vimrc to name a few. As a convention, dotfiles are usually stored in the home directory. You can find yours by typing echo $HOME on your shell. On my machine, it shows /Users/haali.

Getting started is straight forward. We need to organize our dotfiles in a directory. This is something you need to do only once since later the directory containing all of our dotfiles will be stored on Git. To organize our files, we will need to move/copy our dotfiles from the $HOME directory to a new directory. We will refer to that new directory as $dir.

Original copies are to be stored in $dir

For this post, let’s assume we want to track .vimrc.gitconfig and .zshrcbut feel free to add as many dotfiles as you want. On your terminal, run the following two statements:

❯ mkdir $HOME/Documents/dotfiles
❯ cp $HOME/{.vimrc, .gitconfig, .zshrc} $HOME/Documents/dotfiles

If you’ve never written bash previously, the first statement creates a directory dotfiles in the given path and the second statement copies the selected files to the dotfiles folder. FYI, this is the only time you will type those statements for this particular automation. In the future, you will simply retrieve your dotfiles from git and run a script.

Creating the script

Open your editor of choice and create a new file dotfiles_setup.sh with the following line at the very top:

#!/bin/bash

This tells the process that this script should always be run with bash, rather than another shell.

Next, let’s store the dotfiles we care about in a variable. We will also need a variable to store the path of the created directory that has the original dotfiles.

dotfiles=(".vimrc" ".zshrc" ".gitconfig")
dir="${HOME}/Documents/dotfiles"

Moving on, as a convention, most dotfiles are read from the $HOME directory. Having moved our dotfiles away from the $HOMEdirectory, we will need a way to create a link connecting each moved file from $HOME to $dir. Fortunately, this is easily accomplished by using the ln command. The link command basically creates a copy that points to the original file.

Original copies are stored in $dir. $HOME contains pointer dotfiles

Continuing along with the script, add the following lines:

for dotfile in "${dotfiles[@]}";do
ln -sf "${HOME}/${dotfile}" "${dir}"
done

This code segment has a for loop at the beginning which loops over every element of $dotfiles defined earlier and uses the ln command to create a soft link that points to the original dotfile which was moved to $dir. A soft link is a special kind of file that points to another file in the file system and doesn’t contain the data in the target file.

That’s it! Head over to your terminal and let the magic happen with:

./dotfiles_setup.sh

If you head over to $HOME and run ls -la $HOME, you will be able to visually see all the created references to $dir. In the $HOME directory, the dotfile references will be shown with an arrow pointing to the original copy. On my machine for instance .gitconfig is seen as:

.gitconfig -> /Users/haali/Documents/dotfiles/.gitconfig

Making changes

Any changes made to $dir will be seen momentarily by the reference files so you don’t have to do anything special. I strongly recommend you keep your dotfile synced with git so that you could replicate your most up-to-date machine configurations on any machine.

The whole script

#!/bin/bash
dotfiles=(".vimrc" ".zshrc" ".gitconfig")
dir="${HOME}/Documents/dotfiles"
for dotfile in "${dotfiles[@]}";do
ln -sf "${HOME}/${dotfile}" "${dir}"
done

I hope this post will get you to start automating all the things. Credit where credit’s due, I want to thank my coworker Edouard for inspiring me to get started with automating all the things.

More by Hassan Ali

Topics of interest

More Related Stories