267

I found there is some differences between the utility command I used on the mac OSX and linux. I want to make my experience united.

How could I replace all my mac utilities with GNU utilities?

steveyang
  • 2,835
  • 2
    See also http://apple.stackexchange.com/questions/71119/benefit-of-using-macports-coreutils-instead-of-stock-os-x. – lhf Nov 09 '12 at 23:44
  • 2
    Here's a guide https://www.topbug.net/blog/2013/04/14/install-and-use-gnu-command-line-tools-in-mac-os-x/ – Dennis Mar 19 '15 at 08:50
  • 25
    I sympathize with your frustrations but I believe that, in the long term, it will cause greater frustration if they are replaced - After seeking to do the same thing I'd recommend using homebrew as mentioned below, and then just learning to use the utilities with a g ( gsed, greadlink, etc ) instead of replacing the system utilities. – cwd Mar 29 '15 at 13:51
  • For grep, see http://apple.stackexchange.com/questions/193288/how-to-install-and-use-gnu-grep-in-osx – Dan Pritts Apr 19 '16 at 17:28
  • 7
    I disagree with @cwd, using --with-default-names is only affects the local user. It could be an issue with mac oriented terminal utilities, but if you use homebrew for everything, you might aswell pretend you're using linux. Mixed with iterm2, it's working great for me, I can basically pretend I'm home with my linux boxes. – Ray Foss Jun 30 '17 at 17:39
  • NOTE: cp and mv might be dangerous to file’s extended attributes (e.g., tags, invisible, alias, bundle, and more). For details, see these two articles:

    http://brettterpstra.com/2014/07/03/mavericks-tags-and-coreutils-a-warning/

    http://brettterpstra.com/2014/07/04/how-to-lose-your-tags/

    They are a little dated, but I just want to raise the warning so you can investigate if using GNU’s mv and cp will interfere with your needs.

    – Zearin Dec 14 '18 at 16:34
  • 5
    Does anyone have a concrete example demonstrating that this "will cause greater frustration"? – cambunctious Feb 28 '20 at 21:24
  • @cambunctious concrete example: a script that uses the default utility for your system will break. – De Novo Jan 16 '21 at 21:39
  • 1
    @DeNovo that's not concrete – boileau Mar 02 '21 at 14:35
  • @boileau I'd say its concrete enough. Any installation script for a package that tries to use your default utilities based on your OS may fail or do strange things and cause strange errors. That would be quite painful I think. When it will happen who knows, but it is quite likely! – Code Novitiate Aug 05 '22 at 01:35
  • 1
    @CodeNovitiate sorry but saying "here is a vague category of things that might happen" is not concrete. Concrete would be a link to a script that fails and a description of how. – boileau Aug 18 '22 at 15:30
  • Yes, great question. It is a pity. After decades of using gnu untilities, these more classic shell commands just seem broken. For example it seems absurd to have xargs without a -d flag. It requires so many extra keystrokes just to deal with output from grep -l to update files. And I have yet to figure out why sed -i -e ... results in appending -e to all the filenames. – user6856 Jul 31 '23 at 21:02

7 Answers7

309

This adds symlinks for GNU utilities with g prefix to /usr/local/bin/:

brew install coreutils findutils gnu-tar gnu-sed gawk gnutls gnu-indent gnu-getopt grep

See brew search gnu for other packages. If you want to use the commands without a g prefix add for example /usr/local/opt/coreutils/libexec/gnubin before other directories on your PATH.

$ brew info coreutils
coreutils: stable 8.21
http://www.gnu.org/software/coreutils
Depends on: xz
/usr/local/Cellar/coreutils/8.20 (208 files, 9.4M)
/usr/local/Cellar/coreutils/8.21 (210 files, 9.6M) *
https://github.com/mxcl/homebrew/commits/master/Library/Formula/coreutils.rb
==> Caveats
All commands have been installed with the prefix 'g'.

If you really need to use these commands with their normal names, you
can add a "gnubin" directory to your PATH from your bashrc like:

    PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"

Additionally, you can access their man pages with normal names if you add
the "gnuman" directory to your MANPATH from your bashrc as well:

    MANPATH="/usr/local/opt/coreutils/libexec/gnuman:$MANPATH"
Max
  • 225
Lri
  • 105,117
  • 9
    FWIW, I have a Homebrew Formula that acts as a meta-package for all those great GNU utils: see shiny-and-gnu.rb in https://github.com/al-the-x/homebrew-mine/ – AL the X May 13 '14 at 20:47
  • 1
    The first PATH works, but MANPATH failed, why? Is it because I'm using OSX10.10? I echoed $MANPATH, and I got /usr/local/opt/coreutils/libexec/gnuman:, seems original MANPATH wasn't include. After commented out the MANPATH conf in my bashrc, I got nothing by ecoh $MANPATH. And of course, if I use man pwd, I got the BSD manual. How to fix this? – Zen Mar 05 '15 at 15:42
  • 4
    For findutils, you need to add PATH="/usr/local/Cellar/findutils/4.4.2/bin:$PATH" which is not stated in the installation console output. – Sridhar Sarnobat Apr 28 '15 at 20:09
  • 3
    In addition, to get the right man page for findutils, add this to your $MANPATH /usr/local/opt/findutils/share/man – Christian Long Aug 03 '15 at 19:05
  • 6
    @Zen: the right way to initiate MANPATH so as to keep the default system value is: MANPATH="/usr/local/opt/coreutils/libexec/gnuman:${MANPATH-/usr/share/man}". The key is in the construct ${var-default_value}. – dan Oct 06 '15 at 07:43
  • Is there a package available that installs all of these tools at once? – Behrang Saeedzadeh Oct 11 '15 at 01:38
  • I'm running this to generate symlinks in my ~/bin directory: utilDir=coreutils/8.25; cp -a /usr/local/Cellar/${utilDir}/libexec/gnubin/* ~/bin Just change the utilDir for each set of utilities you want to link. Then I can just set `PATH="/home/me/bin:$PATH" without making such a mess with different directories. – vastlysuperiorman Sep 26 '16 at 21:15
  • @danielAzuelos, it seems your snippet has some weird Unicode chars in it which show up when copy-pasting: https://i.imgur.com/qQWygg2.png – Timothy Zorn Feb 02 '17 at 00:47
  • @Sridhar-Sarnobat What's that for? – Franklin Yu Apr 01 '17 at 17:04
  • I don't remember. But I needed it for mine to work. I guess it would not use the GNU version of find or some other common program, which you can always tell when getting an error using find without a directory argument. – Sridhar Sarnobat Apr 01 '17 at 21:08
  • 1
    Setting PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH" helped. Thanks! – Anirudh Murali May 20 '17 at 19:35
66

Besides brew install coreutils, you may also need to install some other packages, such as gnu-sed, grep:

brew install findutils
brew install gnu-indent
brew install gnu-sed
brew install gnutls
brew install grep
brew install gnu-tar
brew install gawk

Note that the --with-default-names option is removed since January 2019, so each binary has to be added to the path if they are to be used without the g prefix.

Old reference (when --with-default-names was available): http://www.topbug.net/blog/2013/04/14/install-and-use-gnu-command-line-tools-in-mac-os-x/

Max
  • 225
xuhdev
  • 829
  • Note that brew install gawk (unlike all the others) will replace awk (via a symbolic link /usr/local/bin/awk). If you want to keep the original /usr/bin/awk, just rm /usr/local/bin/awk – wisbucky Jun 01 '19 at 10:48
  • Is there a GNU version of ping available? – HappyFace Mar 16 '21 at 14:46
  • @HappyFace I don't think so. On GNU/Linux, ping is a Linux kernel utility: https://github.com/iputils/iputils/ – xuhdev Mar 16 '21 at 21:19
25

I'm not sure that I would recommend replacing them; however, you can install them to a different path and utilize them that way. Overall, if you are coming from Linux and would like access to more "generic" *nix utilities, and a system similar to apt, then I would recommend looking into Macports: http://www.macports.org

It allows, for example, using the latest "generic" GCC, as opposed to/in addition to Apple's included GCC, just as an example.

Jonathan
  • 787
  • 3
    For instance, tar and zip from Mac OS X know about metadata that the GNU versions do not. – lhf Oct 22 '12 at 17:49
  • 1
    There are Apple supplied apps, which are just GUIs for some command line tools and if you replace them the apps may start behaving strangely, so go with adding, not replacing. – Ɱark Ƭ Oct 23 '12 at 11:56
  • Right; something like Macports adds them, it doesn't replace them. – Jonathan Oct 23 '12 at 12:10
  • 3
    If you want to use the GNU utilities by default with MacPorts you can add /opt/local/libexec/gnubin to the front of your PATH environment variable. – markshep Sep 26 '16 at 11:59
13

I've written a script to do exactly this! The script can be viewed here (or below). However, I can't always guarantee this post will reflect the latest version of the script linked previously.

Upon running the script, Homebrew will be installed (if not already), all the associated GNU utilities will be installed (if not already), and the PATH variable will be built from the installed utilities.

#!/bin/bash

Install Homebrew (if not already installed)

/bin/bash -c "$(curl -fsSL "
"https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Install required packages from Homebrew

brew tap homebrew/dupes brew install coreutils binutils diffutils ed findutils gawk gnu-indent gnu-sed
gnu-tar gnu-which gnutls grep gzip screen watch wdiff wget bash gdb gpatch
m4 make nano file-formula git less openssh python rsync svn unzip vim
--default-names --with-default-names --with-gettext --override-system-vi
--override-system-vim --custom-system-icons

Empty the .bash_path file that holds GNU paths

[[ -f ~/.bash_path ]] && mv ~/.bash_path ~/.bash_path.orig

Build PATH variable script in ~/.bash_path

for i in /usr/local/Cellar///bin; do echo 'export PATH="'$i':$PATH"' >> ~/.bash_path done for i in /usr/local/Cellar///libexec/gnubin; do echo 'export PATH="'$i':$PATH"' >> ~/.bash_path done for i in /usr/local/Cellar///share/man; do echo 'export MANPATH="'$i':$MANPATH"' >> ~/.bash_path done for i in /usr/local/Cellar///libexec/gnuman; do echo 'export MANPATH="'$i':$MANPATH"' >> ~/.bash_path done

Check if .bash_path is being called from .bash_profile

PATCH=grep "~/.bash_path" ~/.bash_profile if [ "$PATCH" == "" ]; then

Add Ubuntu-style PS1 to .bash_profile

cat <<EOF > ~/.bash_profile export PS1="[\033[1;32m]\u@\h[\033[0m]:[\033[1;34m]\w[\033[0m]# " EOF

Add .bash_path to .bash_profile

echo "source ~/.bash_path" >> ~/.bash_profile fi

nohillside
  • 100,768
Clay Freeman
  • 341
  • 4
  • 10
12

I have written a script that transparently transforms the macOS CLI into a fresh GNU/Linux CLI experience by

  • installing missing GNU programs
  • updating outdated GNU programs
  • replacing pre-installed BSD programs with their preferred GNU implementation
  • installing other programs common among popular GNU/Linux distributions

https://github.com/fabiomaia/linuxify

git clone https://github.com/fabiomaia/linuxify.git
cd linuxify/
./linuxify install

It also allows you to easily undo everything.

./linuxify uninstall
fabiomaia
  • 221
2

As an alternative to setting the PATH and MANPATH environment variables (which I would actually recommend), it is also possible to symlink binaries to an existing PATH location like this:

You need to know where Homebrew installs coreutils binaries.

/usr/local/opt/coreutils/bin

The /usr/local/opt directory is where Homebrew stores relatively static files that are unlikely to change between updates.

Then you can create symbolic links from there to a location that is already on your PATH. It must be a path that is loaded early on PATH, because the PATH is searched on a first-come, first-serve basis. /usr/local/bin is a good choice based on looking at echo $PATH.

which sha256sum # prove it is not on PATH
ln -s /usr/local/opt/coreutils/bin/sha256sum /usr/local/bin/
which sha256sum # prove it is on PATH

This way, it would almost as easy to create symbolic links. In some cases, like when you want tighter control, it is a good option rather than adding an entire directory to your PATH and MANPATH.

Jonathan Komar
  • 895
  • 3
  • 12
  • 21
0

I agree with using brew install coreutils to install the tools. But if you want to use them without the g prefix and are using Oh My Zsh, you can add gnu-utils to your zshrc file to do enable this easily:

plugins=(... gnu-utils)

More info available here: https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/gnu-utils

nofinator
  • 101
  • How does this impact shell scripts expecting the BSD version of commands? – nohillside Nov 16 '22 at 14:55
  • 1
    @nohillside The plugins should be set in your .zshrc file, so their effect should only apply to interactive shells rather than scripts. – nofinator Dec 15 '22 at 15:44
  • the only problem I see with this is: what if you want to bring some user scripts that work in a GNU/Linux environment to macOS? – 40detectives Apr 10 '23 at 14:04