How to remove dir background in `ls -color` output

11,489

Solution 1

To remove all background colors, stick the following into your ~/.bashrc :

eval "$(dircolors -p | \
    sed 's/ 4[0-9];/ 01;/; s/;4[0-9];/;01;/g; s/;4[0-9] /;01 /' | \
    dircolors /dev/stdin)"

Solution 2

Quick solution:

Enter these two commands in the Bash command line:

dircolors -p | sed 's/;42/;01/' > ~/.dircolors
source ~/.bashrc

Explanation:

There is a program dircolors intended to set up the config for ls. The default ~/.bashrc script loads the config with these lines:

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"

Because by default the file ~/.dircolors does not actually exist the script uses the built-in Bash config (eval "$(dircolors -b)").

To remove green background for o+w ('writable by others' permission marked by last 'w' in drwxrwxrwx notation in ls) directories you need to create this file basing on the current (built-in) config. In the command line type the following:

dircolors -p > ~/.dircolors

dircolor -p prints the current config and > redirects the output to the given file.

Now open the file in an editor and find the following line:

OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky

change the number 42 (denoting green background) to 01 (no background) and save changes. Alternatively you can do it with sed program and its substitution feature ('s/PATTERN/NEW_STRING/' syntax) from the command line directly:

sed -i 's/;42/;01/' ~/.dircolors

Above 2 things can be achieved by a single command using a pipe '|':

dircolors -p | sed 's/;42/;01/' > ~/.dircolors

To get the change to take the effect (without restarting the shell), type:

source ~/.bashrc

Solution 3

LS_COLORS is the variable that's referred by ls for colouring its output. If LS_COLORS isn't set, it's generated using dircolors behind the scenes. This can be set manually too with/out using dircolors (see Vivid below).

If most defaults work and you want only a few to be fixed, the easiest is to just set them in your .bashrc.

LS_COLORS=$LS_COLORS:'tw=00;33:ow=01;33:'; export LS_COLORS

This replaces the background colour (42) with normal(00) and bold (01) for

  1. Others-writable directories with sticky bit set (tw)
  2. Others-writable directories without sticky bit (ow)

This is the simplest solution since we keep the defaults for the rest.

The other answer's technique

# -b: make dircolors generate for bash
# sed replaces offending background colors
# sed's output is fed as input for another instance of dircolors
# the entire subshell returns LS_COLORS that's `eval`uated
eval $(dircolors -b | sed 's/ 4[0-9];/ 01;/; s/;4[0-9];/;01;/g; s/;4[0-9] /;01 /' | dircolors /dev/stdin)

simply does this on the fly by getting all the colour values and replacing anything with a background (4[0-9]) with bold (01).


There're better alternatives avoiding all manual fiddling:

  1. LS_COLORS (the project; not to be confused with $LS_COLORS, the variable)
    • Curated set of colours for different file formats/extensions
    • Download latest version, evaluate and append to .bashrc
wget https://raw.github.com/trapd00r/LS_COLORS/master/LS_COLORS -O $HOME/.config/LS_COLORS
echo 'eval $(dircolors -b "$HOME/.config/dircolors")' >> $HOME/.bashrc
  1. Vivid
    • Multiple themes
    • Generates LS_COLORS on-the-fly
    • Set $LS_COLORS in .bashrc using vivid command that generates necessary colour codes based on theme
export LS_COLORS="$(vivid generate molokai)"

Both these tool colour schemes don't have background colour for directories of any kind.

Solution 4

The explanation is given in the output of dircolors -p, e.g.,

screenshot with dircolors -p

Of course dircolors doesn't color its output. I used this script:

#!/usr/bin/perl -w

use strict;

our $comment = "\e[31m";
our $reset   = "\e[K\e[m";

our @data;

open my $fh, "dircolors -p|" or die "cannot read from dircolors";
@data = <$fh>;
close $fh;

printf "\e[H\e[2J";

for my $n ( 0 .. $#data ) {
    chomp $data[$n];
    if ( $data[$n] =~ /^\s*#/ ) {
        printf "%s%s%s\n", $comment, $data[$n], $reset;
    }
    elsif ( $data[$n] =~ /^\s*TERM\s/ ) {
        printf "%s\n", $data[$n];
    }
    elsif ( $data[$n] =~ /^\s*[^\s]+\s+\d+(;\d+)?\s*(#.*)?$/ ) {
        my $code = $data[$n];
        $code =~ s/^\s*[^\s]+\s+//;
        $code =~ s/\s.*//;
        my $data = $data[$n];
        $data =~ s/(#.*)$/$comment$1$reset/;
        $data =~ s/^(\s*)([^\s]+)(\s+)/$1\e[${code}m$2\e[m$3/;
        printf "%s\n", $data;
    }
    else {
        printf "%s\n", $data[$n];
    }
}

1;

To get rid of the background, you can either change the directory permissions, or use a different database to set your LS_COLORS environment variable. The dircolors documentation is the place to go.

Share:
11,489

Related videos on Youtube

chikadance
Author by

chikadance

Updated on June 11, 2022

Comments

  • chikadance
    chikadance almost 2 years

    I use default Linux Mint .bashrc, here is full bashrc, the output is like:

    enter image description here

    some dir has green background, How to remove it?

    • legends2k
      legends2k over 3 years
      The simplest and cleanest is LS_COLORS=$LS_COLORS:'tw=00;33:ow=01;33:'; export LS_COLORS, see answer below.
  • Alfredo Hernández
    Alfredo Hernández over 5 years
    They are removed for the output of ls, but they still show when using autocomplete in zsh. Any workaround for this?
  • Rafael Kitover
    Rafael Kitover over 5 years
    The colors for ls are set in the LS_COLORS environment variable, if the zsh code uses these colors it should work correctly, if it uses something else it will not work.
  • Alfredo Hernández
    Alfredo Hernández over 5 years
    I found the issue. For some weird reason, the eval needs to be defined after the plugins, but before source $ZSH/oh-my-zsh.sh (I use Oh My Zsh), otherwise it's not fully loaded.
  • legends2k
    legends2k over 3 years
    For this method to work, I'd to put eval "$(dircolors -b ~/.dircolors)" in my .bashrc as Bash 5.0.18 doesn't automatically pick up ~/.dircolors or ~/.dir_colors as the man page says on macOS 10.15.7.