Anthony
Anthony

Reputation: 83

Tree command on OS X Bash

OS: MacOS Mojave 10.14.6 Shell: Bash 5.0.11 (Homebrew's Bash)

I installed the tree formula from , but am having difficulty in getting it to output in the colors that I want.

The system default $LSCOLORS for mac is LSCOLORS=exfxcxdxbxegedabagacad. In my .bash_profile, mine is set to LSCOLORS=gxcxdxdxbxxxxxbxbxgxgx. I also have CLICOLOR=1 set.

If I leave my .bash_profile like this and run ls, the output shows in the colors I want. However, when I run tree, the output shows the system default colorization.

I have tried changing $LSCOLORS to $LS_COLORS, because that is what the man page for tree suggests. The "ls" command still shows the correct colors, but this results in tree printing everything in default colors (no colorization at all). The same goes when $TREE_COLORS is set.

Any ideas?

Upvotes: 2

Views: 3520

Answers (2)

Carl
Carl

Reputation: 1019

The problems stem from GNU's tree not playing well with the BSD-based macOS's color environment variables, as explained in the previous answer.

I only managed to get this working by forcing colors with tree -C.

A drawback with a simple alias as alias tree='tree -C' is that this will print ANSI color codes also when the output is sent to something else than a terminal, e.g. when redirecting to a file: tree > file.txt. To see the messy output, try with e.g. tree -C | cat -v.

I get around this by using a custom function instead of an alias.

In .bash_profile or .zshrc:

function tree() {
  local treeArgs=(-I __pycache__)    # list any desired default arguments
  _isTerminal() { [[ -t 1 ]]; }
  _isTerminal && treeArgs+=(-C)      # conditionally force color
  command tree "${treeArgs[@]}" "$@" # run the command
  unset -f _isTerminal
}

Tested with bash 5.1 and zsh 5.8.1.

Upvotes: 0

Anthony
Anthony

Reputation: 83

On OS X, the $LSCOLORS variable defines the colored output for the ls command. Because tree isn't a native command for OS X, it looks for the GNU variables and their associated formats to determine what color to use. If these aren't set, it will use the system defaults.

If you don't have GNU commands installed, you can get them from homebrew by running:

brew install coreutils

In order to avoid conflicts with OS X commands, all GNU commands are installed prefixed with a g. So entering ls would run the OS X version of the ls command, while entering gls runs the GNU version of the ls command.

Once the GNU commands are installed, you have to set your color variables in the way that a Linux system would understand. Running the command dircolors on a GNU shell gives you the default value for the $LS_COLORS variable. So because all commands are installed prefixed with a g, run gdircolors. Copy the output into your .bash_profile, and modify colors as desired.

This is a really in depth guide about what each of the keys means, and what codes correspond to which colors: http://www.bigsoft.co.uk/blog/2008/04/11/configuring-ls_colors The system also provides a guide, although it is less in depth. To see this, run gdircolors -p.

Now, I have both variables defined in my .bash_profile.

export CLICOLOR=1 
export LSCOLORS=gxcxdxdxbxxxxxbxbxgxgx

This first enables colored output, then defines the colors that the OS X version of the ls command uses.

LS_COLORS='rs=0:di=36:ln=32:mh=00:pi=33:so=33:do=33:bd=00:cd=00:or=05;36:mi=04;93:su=31:sg=31:ca=00:tw=36:ow=36:st=36:ex=031:*.tar=00:*.tgz=00:*.arc=00:*.arj=00:*.taz=00:*.lha=00:*.lz4=00:*.lzh=00:*.lzma=00:*.tlz=00:*.txz=00:*.tzo=00:*.t7z=00:*.zip=00:*.z=00:*.dz=00:*.gz=00:*.lrz=00:*.lz=00:*.lzo=00:*.xz=00:*.zst=00:*.tzst=00:*.bz2=00:*.bz=00:*.tbz=00:*.tbz2=00:*.tz=00:*.deb=00:*.rpm=00:*.jar=00:*.war=00:*.ear=00:*.sar=00:*.rar=00:*.alz=00:*.ace=00:*.zoo=00:*.cpio=00:*.7z=00:*.rz=00:*.cab=00:*.wim=00:*.swm=00:*.dwm=00:*.esd=00:*.jpg=00:*.jpeg=00:*.mjpg=00:*.mjpeg=00:*.gif=00:*.bmp=00:*.pbm=00:*.pgm=00:*.ppm=00:*.tga=00:*.xbm=00:*.xpm=00:*.tif=00:*.tiff=00:*.png=00:*.svg=00:*.svgz=00:*.mng=00:*.pcx=00:*.mov=00:*.mpg=00:*.mpeg=00:*.m2v=00:*.mkv=00:*.webm=00:*.ogm=00:*.mp4=00:*.m4v=00:*.mp4v=00:*.vob=00:*.qt=00:*.nuv=00:*.wmv=00:*.asf=00:*.rm=00:*.rmvb=00:*.flc=00:*.avi=00:*.fli=00:*.flv=00:*.gl=00:*.dl=00:*.xcf=00:*.xwd=00:*.yuv=00:*.cgm=00:*.emf=00:*.ogv=00:*.ogx=00:*.aac=00:*.au=00:*.flac=00:*.m4a=00:*.mid=00:*.midi=00:*.mka=00:*.mp3=00:*.mpc=00:*.ogg=00:*.ra=00:*.wav=00:*.oga=00:*.opus=00:*.spx=00:*.xspf=00:';

export LS_COLORS

This defines the colors that the GNU version of the ls command uses. This is also the color scheme that the tree command uses (and I'm guessing all other GNU commands).

It is also possible to store these variables in a file, such as .dircolors and simply add the following line to your .bash_profile instead:

source '/path/.dircolors'

In the above, make sure to substitute path with the path to the .dircolors file. However, I prefer to keep everything neatly in one place, namely my .bash_profile.

Upvotes: 5

Related Questions