If you've ever looked at your .bashrc file and wondered how the heck it got so weirdly out of control, look no further than the slow migration of "local changes" to the .local folder, and the number of language– or framework-specific environments that are now kept there.

There's much to recommend this move, not the least of which is decluttering the $HOME directory. But my biggest pet peeve was the $PATH variable, which seemed to just grow and grow in my .bashrc file into an unreadable string. I've decided to fix that. Here's how.

I had recently added Google Go to my list of environments, and I couldn't figure out where to add it into the PATH. I mean, look at this beast:

export PATH="/home/elf/.pyenv/plugins/pyenv-virtualenv/shims:/home/elf/.pyenv/shims:/home/elf/.cargo/bin:/home/elf/bin:/home/elf/.local/bin:/home/elf/.local/lib/yarn/bin:/home/elf/.pyenv/bin:/home/elf/.local/lib/npm-packages/bin:/usr/local/bin:/snap/bin:/opt/wine-stable/bin:/usr/bin:/bin:/usr/games:/usr/local/go/bin"

There are two things I wanted to do: break that massive path variable into a readable and manageable list of paths, and then join the elements of that list together into an exportable string with a minimal amount of code.

So the first thing to know is that bash has arrays! They're not the world's greatest thing, but they're fit for this purpose. I took my path and broke it up into a local PATHS array:

PATHS=(
	"/bin"
	"/usr/bin"
	"/home/elf/bin"
	"/home/elf/.cargo/bin"
	"/home/elf/.local/bin"
	"/home/elf/.pyenv/bin"
	"/home/elf/.local/lib/yarn/bin"
	"/home/elf/.local/lib/npm-packages/bin"
	"/home/elf/.local/share/go/bin"
	"/usr/local/bin"
	"/snap/bin"
	"/opt/wine-stable/bin"
	"/usr/games"
)

That's a HECK of a lot more readable, no? (I know, I know, it's probably an awful mess, but it's my mess, and at least it's somewhat organized.)

Now how do we export that as the PATH?

I recalled that awk has field and record separators, and while I was searching to see if I could use awk as a way of assembling the string, I discovered that bash has a field separator control! As long as the field separator is a single character you can use it to control the rendering of a bash array. I'll admit up front I don't know if that's "ASCII character" or "Unicode character" or "Unicode code point", and for my purposes it doesn't make a difference, since the path separator symbol is the colon, hex 0x3A, which makes it fit easily in UTF-8, but it might for someone with other linguistic needs.

Anyway, it's easy to turn the array above into a single string:

export PATH=$( IFS=":" ; echo "${PATHS[*]}" )

The $() construct isolates the rendering into a separate process, sets the field separator to a colon, then echos out all the contents of the PATHS variable separated by the field separator. The resulting string is then exported as PATH.

And that's how you use bashisms to help organize your shell code into more readable chunks.


Postscript: It's professional malpractice if you're writing a lot of bash and you're not using shellcheck. Just sayin'. It could save you a lot of grief.