2 minute read

In the past six months, I’ve had the (dis)pleasure of re-formatting my MacBook too many times. Each time, I’ve opted to use the Migration Assistant to preserve any installed programs or special configurations that I’ve come to get used to on my older computer. That being said, I realized that it’s a slow and arduous process and that I should make better use of the opportunity that I’ve been given.

Hence, I decided to create an idempotent bash script that I can copypasta from my Github for any new macs that I get and can instantly get all my necessary shortcuts, settings, and development tools quickly and painlessly. I’ve found something similar on github, so that was a nice sign that what I’m doing is actually a problem worth solving. When I mentioned this to one of our interns, he said it reminded him of something similar for Windows. It’s a website that zips together all downloadable software that may be of use to someone when they’re setting up a new computer.

To start, there are certain features that I would like to have in my script:

  • idempotency (i.e. I can run this script as many times as I want and it will deliver to me the desired state of the machine)
  • a folder called “dev” where I check out all my git repos
  • aliases for my bash_profile/bashrc so that I can do “ll” instead of “ls -l”
  • homebrew installed
  • applications that I can install from homebrew installed (ruby, python, vscode, gitkraken, bundler)
  • follow clean code best practices

After starting, I had forgotten a lot of the neat little syntax that is bash.

  1. I learned the difference between [ and [[, the latter can match for regex, sets an exit code, doesn’t need to quote variable substitutions, and is an overall upgrade from the former. That being said, the former is POSIX and is supported across all shells.

  2. I remembered that bash scripts are generally run in a sub-shell so sourcing the .bash_profile or .bashrc will not apply to the main shell. In order to get around this, an easy way is to run the main script using source, such as source setup-mbp.sh.

Did you know? .bash_profile is for macs and .bashrc is commonly used for linux

  1. The super performant way to check if there’s output to a certain command is the following:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi

Instead of storing the result into the buffer, store only the first character and count whether it is equal to 0 (for no output) or 1 (for output). Ref: Link

I’ll keep on working at this and refactoring to make it better and more robust.

When I was writing this script, I made smaller test scripts to verify behaviour and syntax. Also, I had to uninstall and install each of the new features to make sure that the script would work for fresh installs as well as macs in a partially configured state. In particular, there’s this piece of code that I want to clean up:

code_extensions() {
  if [[ $(code --list-extensions | grep 'shakram02.bash-beautify' | head -c1 | wc -c) -eq 0 ]]; then
    code --install-extension shakram02.bash-beautify
    code_extensions
  else
    echo "VSCODE:: extensions installed"
  fi
}

Ideally, I would pass in arguments to the code_extensions method to be able to reuse the logic there. Anyway, I’ll continue to work on this and provide updates!

The code can be found on my GitHub, here.