How to organize your bash profile
Tags: bash, tips, commandline
Published: 2020-11-08 15:35:24

For many years, I've treated my bash profile as some alien part on my computer. Over time, I hacked together quite some aliases for often-used commands and just shoved them into this mysterious file.

I recently moved to a new computer and started migrating my data, including my shell shortcuts. Opening them in Atom to cherry-pick what I want to migrate, it dawned on me that my bash profile:
* is just code, the same I write day in day out, nothing alien or mysterious at all (a different language, though)
* is a total mess
* is badly coded

Hence, I thought, why not treat my bash profile the same way, like any other project? This includes:
* a proper structure
* documentation
* linting
* reviewing
* git

So here is what I came up with:

I created a new GitHub repository named `.bashrc.d` and cloned it to my home folder (after some research, I found that this folder naturally exists on some Linux distros, but not on macOS; thus, I choose this name):

```shell
cd ~/ && git clone https://github.com/swiknaba/.bashrc.d.git
```

the folder structure there is as follows:
```
.bashrc.d
│   README.md  
│
└───.github
│   └───workflows
│       │   shell_lint.yml
│   
└───src
│   └───projects
│       │   project_1.bashrc
│       │   project_2.bashrc
    │   constants.bashrc
    │   git.bashrc
    │   paths.bashrc
    │   ruby_on_rails.bashrc
    │   utilities.bashrc
```

Now we need to load all these files in our `.bash_profile`, luckily that is pretty simple:

```bash
#!/bin/bash

# https://github.com/koalaman/shellcheck/wiki/SC2044
shopt -s globstar nullglob
for file in ~/.bashrc.d/src/**/*.bashrc
do
  source "$file"
done
```
So all I have to do is copy-paste this into my new computer's bash profile, then clone my repo, and finally give all files the correct permissions:

```shell
chmod -R 700 ~/.bashrc.d
find ~/.bashrc.d/src -name '*.bashrc' | xargs chmod +x
```

During re-writing all my bash scripts, I realized macOS ships with Bash version 3, which seems to be due to licensing issues. I've upgraded that to Bash 5, which is very straightforward; you can use homebrew for that. Upgrading Bash gives us shiny new features and overall improvements. Looping over files became so much shorter! :rocket:

Many shortcuts in my bash profile are specific to projects that I am working on, so I cannot share the repo with you. However, I can share some parts of it here, in case you are interested in cleaning up and organizing your bash profile, too!

```yml
# .github/workflows/shell_lint.yml

name: ShellLint

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      # Lint bash scripts
      - name: Shell Linter
        uses: azohra/shell-linter@v0.4.0
        with:
          path: "src/*.bashrc, src/**/*.bashrc"
```

For example, the above-mentioned `src/constants.bashrc` contains stuff like:

```bash
# set default terminal-editor to nano
export EDITOR=nano
VISUAL="$EDITOR"
export VISUAL
export BUNDLER_EDITOR=atom

# ignore consecutive duplicates when running `history` in bash
HISTCONTROL=ignoredups
```

The `paths.bashrc` file hosts all these `export PATH=/usr/...` that so many tools shove into your bash profile.

And so forth. I think you get the idea!

Now that I've moved my bash profile to GitHub, I also opened my first issue: Write tests using shUnit2. Let's see, when I find motivation for that :smile:

(How) do you organize code on your machine that is solely in your hands, not peer-reviewed by anyone?