Set Practical ls Colours with a dir_colors File
Your directory listing is one flat colour and the log files you care about hide in it. You will write a small, user-owned dir_colors file that gives directories and log files clear colours, then load it into LS_COLORS with one shell command. It takes about ten minutes and targets GNU dircolors 9.4 from GNU coreutils, with the dir_colors(5) format documented by Linux man-pages 6.7.
The route
Jump straight to the step you need, or tick off Done means at the end.
- You need: GNU
dircolors,lsand a shell. No elevated privileges. - What it touches: your shell environment and directory listings, never the files being listed.
1. Check the installed tools
Start with read-only checks. They confirm which implementation will parse the file, so you do not end up debugging a different command earlier in your PATH:
$ command -v dircolors
/usr/bin/dircolors
$ dircolors --version
dircolors (GNU coreutils) 9.4
$ command -v ls
/usr/bin/ls
Your paths or version may differ. The GNU implementation is the detail that matters. The manual also describes statements accepted by Slackware's implementation, but GNU dircolors ignores its COLOR, OPTIONS and EIGHTBIT statements.
Checkpoint
If dircolors is missing, stop here and use your normal package-management process. Do not copy a configuration from another operating system and assume its parser accepts every keyword.
2. Make a minimal configuration
Choose a user-owned path. The manual names /etc/DIR_COLORS and ~/.dir_colors as conventional locations, but says GNU dircolors ignores them on Debian. Passing the path explicitly makes the source of your settings unambiguous.
First check whether a file already exists. This is read-only:
$ test -e "$HOME/.dir_colors" && ls -l "$HOME/.dir_colors" || echo 'no existing user file'
If it exists and holds settings you want to keep, copy it before editing. The original is untouched:
$ cp --preserve=mode,ownership,timestamps "$HOME/.dir_colors" "$HOME/.dir_colors.bak"
Warning
The following here-document overwrites ~/.dir_colors. Take the backup first, or open the file in an editor and merge these lines instead.
$ cat > "$HOME/.dir_colors" <<'EOF'
# Global rules apply to every terminal type.
NORMAL 0
DIR 01;34
*.log 01;31
# This rule is used when TERM matches this pattern.
TERM xterm-256color
DIR 01;36
EOF
How the file is read:
- Blank lines are ignored, and text after a hash preceded by whitespace is a comment.
- Statements are case-insensitive.
- Scope: a statement before the first
TERMis global. Later statements belong to the matching terminal section. - Overrides: a later terminal-specific declaration can override a global one.
Checkpoint
Inspect the file before loading it.
$ sed -n '1,80p' "$HOME/.dir_colors"
# Global rules apply to every terminal type.
NORMAL 0
DIR 01;34
*.log 01;31
# This rule is used when TERM matches this pattern.
TERM xterm-256color
DIR 01;36
3. Generate LS_COLORS for the current shell
GNU dircolors reads the file and prints shell code. Use -b for Bourne-style shells such as Bash, Dash and Zsh:
$ eval "$(dircolors -b "$HOME/.dir_colors")"
$ printf '%s\n' "$LS_COLORS"
no=0:di=01;34:*.log=01;31:di=01;36:
The exact order and terminal-specific entries depend on TERM. The final di=01;36 is the matching terminal rule overriding the earlier directory rule, which happens when this terminal is xterm-256color. A generated fragment normally holds an LS_COLORS assignment and an export.
Security boundary
eval executes the text printed by dircolors. Only use it with a configuration file you trust. To inspect the generated text first, run dircolors -b "$HOME/.dir_colors" without eval.
Test the result without forcing colour into a log or pipe:
$ mkdir -p /tmp/dir-colors-check
$ touch /tmp/dir-colors-check/example.log /tmp/dir-colors-check/notes.txt
$ ls --color=auto -l /tmp/dir-colors-check
total 0
-rw-r--r-- 1 ... example.log
-rw-r--r-- 1 ... notes.txt
Ownership, timestamps and spacing vary. In an interactive terminal, example.log and the directory name should use the configured styles. The automatic colour option emits colour for a terminal but avoids escape sequences when output is redirected.
4. Load the file automatically, carefully
Once the manual command works, add it to the startup file for the shell you actually use. For Bash, put this line in ~/.bashrc:
eval "$(dircolors -b "$HOME/.dir_colors")"
For a C shell, generate the equivalent form with dircolors -c and adapt it for the relevant startup file:
$ dircolors -c "$HOME/.dir_colors"
setenv LS_COLORS 'no=0:di=01;34:*.log=01;31:di=01;36:'
Warning
Do not paste a Bash assignment into a C shell startup file. Likewise, do not add the line to a system-wide profile when a per-user setting is enough.
Reopen a shell or source the file, then check:
$ . "$HOME/.bashrc"
$ printf 'LS_COLORS is %s\n' "${LS_COLORS:+set}"
LS_COLORS is set
Recovery
To undo the automatic loading, remove the line you added and start a new shell. To undo only the current shell's exported value, run unset LS_COLORS. That does not edit the configuration file.
5. Extend the rules without surprising yourself
Use a leading asterisk for a suffix rule such as *.log. The older form .log is accepted but described as obsolete.
Type rules include DIR, FILE, LINK, FIFO, SOCK, EXEC, ORPHAN and MISSING. Two fall back when absent:
- No
ORPHAN:lsuses the link colour. - No
MISSING:lsuses the regular-file colour.
Colour values are usually ANSI numbers separated by semicolons. For example, 0 resets the display, 1 makes text brighter, 31 selects a red foreground and 44 selects a blue background. Terminals do not all render every attribute the same way. If a terminal stays coloured after a listing, set both NORMAL and FILE to a reset or a suitable normal foreground sequence.
Spaces, control characters, backslashes, carets and a leading hash in a value or extension need escaping. The format accepts C-style escapes: \e for Escape, \n for newline, \_ for space and \# for a literal hash. Keep unusual control characters out of a shared configuration unless you have tested the terminal that will show them.
6. Diagnose a rule that does not apply
First print the generated fragment and check the environment:
$ printf 'TERM=%s\n' "$TERM"
$ dircolors -b "$HOME/.dir_colors"
LS_COLORS='...';
export LS_COLORS
- Terminal rule missing? Its
TERMpattern did not match the currentTERM. - Global rule ignored? The global section ends at the first
TERM. Move the rule above that line if it should apply everywhere. - Assignment looks right, no colour? Check that you are using automatic colour mode, or an alias that enables colour.
LS_COLORSsupplies the mapping. It does not by itself forcelsto emit colour. - Rule does nothing? Test a filename that actually matches it. A rule for
*.logdoes not matchserver.LOG, and this format does not supply case handling.
Keep the temporary test directory until the listing behaves as expected. Then remove it with rm -rf /tmp/dir-colour-check, and only when you are certain it holds nothing useful.
Done means
- Right tool: you confirmed the installed GNU
dircolorsversion and chose the correct shell output form. - Sensible file: your configuration has a global rule and, where needed, a matching
TERMsection. - Reviewed output: you inspected the generated shell code before using
evalon a trusted file. - Colours showing:
LS_COLORSis set in the intended shell and automatic colour mode shows the expected styles. - Reversible: you know how to remove the startup line or unset the current shell variable without changing listed files.