How can I setup a separate bash environment with only GNU utilities on OS X?

First, this is about a lot more than just coreutils. The BSD equivalent to GNU findutils is also quite different, pretty much every command related to dynamic linkage is different, etc.

And then on top of that, you have to deal with versioning differences: OS X still ships a lot of older software to remain on GPL2 instead of GPL3, such as Bash 3.x instead of Bash 4.x. The autotools are also often outdated with respect to bleeding-edge Linux distros.

The answer to the core part of your question is, "Sure, why not?" You can use Homebrew to install all of these alternative GNU tools, then put $(brew --prefix coreutils)/libexec/gnubin and /usr/local/bin first in your PATH to make sure they're found first:

export PATH="$(brew --prefix coreutils)/libexec/gnubin:/usr/local/bin:$PATH"

If for some reason brew installs a package to another location, also include that in the PATH variable.

If you would rather only replace a few packages, the tricky bit is dealing with all the name changes. Whenever brew installs a program that already has an implementation in the core OS, such as when installing GNU coreutils, it names its version differently so that you can run either, depending on your need at the time. Instead of renaming all of these symlinks¹, I recommend that you fix all of this up with a layer of indirection:

$ mkdir ~/linux
$ cd ~/linux
$ ln -s /usr/local/bin/gmv mv
...etc for all the other tools you want to rename to cover OS versions
$ export PATH=$HOME/linux:$PATH
...try it out...

Once you're happy with your new environment, you can put export PATH=$HOME/linux:$PATH into your ~/.bash_profile.

That takes care of interactive use, either with bulk replacement or single application replacement.

Unfortunately, it does not completely solve the shell script problem, because sometimes shell scripts get their own environment, such as when launched from cron. In that case, you could modify the PATH at the top of each cross-platform shell script:

#!/bin/bash
export PATH="$HOME/linux:$(brew --prefix coreutils)/libexec/gnubin:/usr/local/bin:$PATH"

You do not need to make it conditional, since it is just offering the shell another place to look for programs.


Footnotes

  1. e.g. /usr/local/bin/gmv../Cellar/coreutils/$version/bin/gmv

Related Posts

  1. How to replace Mac OS X utilities with GNU core utilities?
  2. Install and Use GNU Command Line Tools on Mac OS X

Tags:

Shell

Osx