3

I am trying to modify LS_COLORS behavior. Presently it (say for sh or py), changes color depending on if it is executable or not, as shown here screenshot from my terminal; one is executable, other is not

But, I want all my script, executable or not, have same color and computer generated executables, e.g. a.out etc have the color defined by ex in LS_COLOR

This is the output of dircolors -p:

# Configuration file for dircolors, a utility to help you set the
# LS_COLORS environment variable used by GNU ls with the --color option.
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# Copying and distribution of this file, with or without modification,
# are permitted provided the copyright notice and this notice are preserved.
# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the
# slackware version of dircolors) are recognized but ignored.
# Below, there should be one TERM entry for each termtype that is colorizable
TERM Eterm
TERM ansi
TERM color-xterm
TERM con132x25
TERM con132x30
TERM con132x43
TERM con132x60
TERM con80x25
TERM con80x28
TERM con80x30
TERM con80x43
TERM con80x50
TERM con80x60
TERM cons25
TERM console
TERM cygwin
TERM dtterm
TERM eterm-color
TERM gnome
TERM gnome-256color
TERM hurd
TERM jfbterm
TERM konsole
TERM kterm
TERM linux
TERM linux-c
TERM mach-color
TERM mach-gnu-color
TERM mlterm
TERM putty
TERM putty-256color
TERM rxvt
TERM rxvt-256color
TERM rxvt-cygwin
TERM rxvt-cygwin-native
TERM rxvt-unicode
TERM rxvt-unicode-256color
TERM rxvt-unicode256
TERM screen
TERM screen-256color
TERM screen-256color-bce
TERM screen-bce
TERM screen-w
TERM screen.Eterm
TERM screen.rxvt
TERM screen.linux
TERM st
TERM st-256color
TERM terminator
TERM vt100
TERM xterm
TERM xterm-16color
TERM xterm-256color
TERM xterm-88color
TERM xterm-color
TERM xterm-debian
# Below are the color init strings for the basic file types. A color init
# string consists of one or more of the following numeric codes:
# Attribute codes:
# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
# Text color codes:
# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
# Background color codes:
# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
#NORMAL 00 # no color code at all
#FILE 00 # regular file: use no color at all
RESET 0 # reset to "normal" color
DIR 01;34 # directory
LINK 01;36 # symbolic link. (If you set this to 'target' instead of a
 # numerical value, the color is as for the file pointed to.)
MULTIHARDLINK 00 # regular file with more than one link
FIFO 40;33 # pipe
SOCK 01;35 # socket
DOOR 01;35 # door
BLK 40;33;01 # block device driver
CHR 40;33;01 # character device driver
ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file
SETUID 37;41 # file that is setuid (u+s)
SETGID 30;43 # file that is setgid (g+s)
CAPABILITY 30;41 # file with capability
STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w)
OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky
STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable
# This is for files with execute permission:
EXEC 01;32
# List any file extensions like '.gz' or '.tar' that you would like ls
# to colorize below. Put the extension, a space, and the color init string.
# (and any comments you want to add after a '#')
# If you use DOS-style suffixes, you may want to uncomment the following:
#.cmd 01;32 # executables (bright green)
#.exe 01;32
#.com 01;32
#.btm 01;32
#.bat 01;32
# Or if you want to colorize scripts even if they do not have the
# executable bit actually set.
#.sh 01;32
#.csh 01;32
 # archives or compressed (bright red)
.tar 01;31
.tgz 01;31
.arc 01;31
.arj 01;31
.taz 01;31
.lha 01;31
.lz4 01;31
.lzh 01;31
.lzma 01;31
.tlz 01;31
.txz 01;31
.tzo 01;31
.t7z 01;31
.zip 01;31
.z 01;31
.Z 01;31
.dz 01;31
.gz 01;31
.lrz 01;31
.lz 01;31
.lzo 01;31
.xz 01;31
.bz2 01;31
.bz 01;31
.tbz 01;31
.tbz2 01;31
.tz 01;31
.deb 01;31
.rpm 01;31
.jar 01;31
.war 01;31
.ear 01;31
.sar 01;31
.rar 01;31
.alz 01;31
.ace 01;31
.zoo 01;31
.cpio 01;31
.7z 01;31
.rz 01;31
.cab 01;31
# image formats
.jpg 01;35
.jpeg 01;35
.gif 01;35
.bmp 01;35
.pbm 01;35
.pgm 01;35
.ppm 01;35
.tga 01;35
.xbm 01;35
.xpm 01;35
.tif 01;35
.tiff 01;35
.png 01;35
.svg 01;35
.svgz 01;35
.mng 01;35
.pcx 01;35
.mov 01;35
.mpg 01;35
.mpeg 01;35
.m2v 01;35
.mkv 01;35
.webm 01;35
.ogm 01;35
.mp4 01;35
.m4v 01;35
.mp4v 01;35
.vob 01;35
.qt 01;35
.nuv 01;35
.wmv 01;35
.asf 01;35
.rm 01;35
.rmvb 01;35
.flc 01;35
.avi 01;35
.fli 01;35
.flv 01;35
.gl 01;35
.dl 01;35
.xcf 01;35
.xwd 01;35
.yuv 01;35
.cgm 01;35
.emf 01;35
# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions
.axv 01;35
.anx 01;35
.ogv 01;35
.ogx 01;35
# audio formats
.aac 00;36
.au 00;36
.flac 00;36
.m4a 00;36
.mid 00;36
.midi 00;36
.mka 00;36
.mp3 00;36
.mpc 00;36
.ogg 00;36
.ra 00;36
.wav 00;36
# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions
.axa 00;36
.oga 00;36
.spx 00;36
.xspf 00;36

I am also setting LS_COLORS in my ~/.bashrc:

  LS_COLORS='no=1:di=1;38;2;66;133;244:ln=09;32:pi=40;32:so=01;35:bd=40;33;01:cd=34;33;01:or=34;33;01:ex=01;38;2;149;138;221:*.in=01;34:*.sh=1;38;2;0;215;95'

As you can see in the image, the ex color is overriding the sh filetype's color when the rename.sh is set as executable.

1
  • 3
    As far as I understand the question you want to change the order of applied colors to different attributes (executable bit and extenstion ".sh" in this case). And as far as I know it is not possible.
    – jimmij
    Jun 21, 2015 at 12:07

2 Answers 2

2

To be pragmatic, you can always replace your ls with a small shell function that post-processes the output of ls. ls is often already an shell alias (to see use: type ls). Though you can use the same name for the function, it is preferable to use a slightly different name like ll to avoid any ambiguity. You soon get used to typing ll instead of ls.

Here is such a shell function (to put eg in your ~/.bash_profile). It uses perl to look for the ansi escape code sequences that set colour surrounding a filename ending in .sh, and replaces them by your desired sequence. You can see these codes by piping your ls --color output through cat -vet. You may need to edit this script if you dont see the same sequence I did. Also, ls may not react the same since the output is a pipe not a tty.

ll(){
    /bin/ls --color "$@" |
    perl -p -e '$want = "1;38;2;0;215;95";
                s/(\e\[)([0-9;]*)(m[^\e]*\.sh\e\[0m$)/$1$want$3/;' 
}

In the perl substitute command (s/pattern/replacement string/) \e is the escape character, \[ is a left bracket ([), [0-9;]* is any sequence of digits and (;), [^\e]* is any characters not including escape, \. is a dot (.), and $ is the end of the line. () are used to capture the matching parts into $1, $2 and $3, used in the replacement part.

If you really want the name ls, keep the function ll and use alias ls=ll so it only works only in interactive shells.

0

Though this question is quite old, still I resolved this problem by modifying and recompiling my ls. Here are a few additional details:

OS: Kubuntu 23.04 (Ubuntu variant) coreutils version: 9.1

What I understood after diving into the source code was that ls checks the LS_COLORS for specific extensions only if they are normal files, not for executables. I just modified the ls to allow it to perform the same color check for executable files.

Here are the steps:

  1. (Be sure you have deb-src repositories enabled)
sudo apt install build-essential
sudo apt-get build-dep coreutils
apt-get source coreutils
cd coreutils-9.1

You may need to change the cd command as per your coreutils version.

  1. Use any editor to open src/ls.c. Search for these lines:
...
/* Check the file's suffix only if still classified as C_FILE.  */
ext = NULL;
if (type == C_FILE)
    {
...

The line to be modified is this one:

if (type == C_FILE)

In my coreutils source, it is line no. 5033, inside function get_color_indicator.

  1. Edit the line to the following:
if ((type == C_FILE) || (type == C_EXEC))

NOTE: As to why we did this, read the comment above that line:

/* Check the file's suffix only if still classified as C_FILE.  */

Scrolling a few lines above we see that the file is classified as C_FILE only if it is a regular file. Files such as executables and multi-hard links (you can see the same lines for other types) are not classified as C_FILE.

Executables are classified as C_EXEC. Modifying that line we allow files with the C_EXEC flag set to be colored differently as well alongside the C_FILE ones.

You can also add other flags (like C_MULTIHARDLINK), if needed, in the same fashion.

  1. Compile your modified ls. For this: (be sure to be in the coreutils-9.1 directory)
./bootstrap
./configure

make clean
make -j $(nproc)

(Refer to this answer for compilation steps if not clear.)

  1. Now you can test with your newly created ls, located at src/ls. Once you are confident enough with your modified ls, you can move your ls to replace /bin/ls. I would actually like to save a backup of older ls, but that's your wish.

Final step: Modify your LS_COLORS and enjoy the beauty of your ls :-)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .