Search code examples
macosdirectoryhomebrewgnuls

How to install and use GNU "ls" on macOS?


I was following this article to update my bash. I really want to update my version of bash so that I can use the --group-directories-first option for the ls command.

So far I have accomplished the following from the linked article:

  • I successfully executed the brew install bash command and downloaded the new bash. Per the article I can verify that the the /usr/local/bin/bash --version on my machine shows the following:

    GNU bash, version 5.0.11(1)-release (x86_64-apple-darwin18.6.0) Copyright (C) 2019 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html

    This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

    • I completed the sudo vim /etc/shells command, editing the file to include the new downloaded bash. This is what it looks like:

enter image description here

  • I executed the chsh -s /usr/local/bin/bash to set the new bash as default.

However, even after I close the terminal and relaunch it, I am not sure if I am using the new terminal. This is because:

  1. when I execute bash --version I get the following:

    GNU bash, version 5.0.11(1)-release (x86_64-apple-darwin18.6.0) Copyright (C) 2019 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html

    This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

But when I run echo $BASH_VERSION I get something to the contrary (3.2.57(1)-release). Isn't that the old verison?

  1. Also, the new "group directories first" command still doesn't work. I get the following error when I run ls --group-directories-first:

ls: illegal option -- - usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]

Any help or pointers would be greatly appreciated.

Thanks!


Solution

  • This has nothing to do with bash. Command ls is not a builtin of bash.

    macOS is based on the Unix operating system. Some of its basic commands are BSD flavored. The --group-directories-first option you want is available in GNU ls only. All you need is a GNU flavored ls.

    Solution: install coreutils, in which GNU ls is included.

    brew install coreutils
    

    Add the following code into ~/.bash_profile, to prioritize the ls command and other GNU flavored commands over the builtin BSD flavored command in macOS.

    # Make all GNU flavor commands available, may override same-name BSD flavor commands
    # For x86 Mac
    export PATH="/usr/local/opt/coreutils/libexec/gnubin:${PATH}"
    export MANPATH="/usr/local/opt/coreutils/libexec/gnuman:${MANPATH}"
    
    # For M1 Mac
    export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:${PATH}"
    export MANPATH="/opt/homebrew/opt/coreutils/libexec/gnuman:${MANPATH}"
    

    If you only want the GNU ls but not other GNU flavored commands. Don't add the above content, but create an alias in ~/.bash_profile.

    # For x86 Mac
    alias ls="/usr/local/opt/coreutils/libexec/gnubin/ls"
    
    # For M1 Mac
    alias ls="/opt/homebrew/opt/coreutils/libexec/gnubin/ls"
    

    Here's all commands brought by coreutils.

    ❯ ls /usr/local/opt/coreutils/libexec/gnubin
    '['         cat      cksum    dd          echo     fmt      install   ls       mv       od         printf     rmdir       sha384sum   split    tac       tr         unexpand   wc
     b2sum      chcon    comm     df          env      fold     join      md5sum   nice     paste      ptx        runcon      sha512sum   stat     tail      true       uniq       who
     base32     chgrp    cp       dir         expand   groups   kill      mkdir    nl       pathchk    pwd        seq         shred       stdbuf   tee       truncate   unlink     whoami
     base64     chmod    csplit   dircolors   expr     head     link      mkfifo   nohup    pinky      readlink   sha1sum     shuf        stty     test      tsort      uptime     yes
     basename   chown    cut      dirname     factor   hostid   ln        mknod    nproc    pr         realpath   sha224sum   sleep       sum      timeout   tty        users
     basenc     chroot   date     du          false    id       logname   mktemp   numfmt   printenv   rm         sha256sum   sort        sync     touch     uname      vdir