简体   繁体   中英

ls output colors for specific files?

Is it possible to assign the ls command's output colors for specific files? The reason I ask is that for git repositories, I want my tracked files to have different colors from untracked ones. So specifically, I want to take the output of "git ls-files" and give those files a certain color (or make the names bold or whatever).

For a standard ls command, it is quite easy. Let's say you want to show all .mp3 files in a purple color, then run:

$ LS_COLORS=$LS_COLORS:"*mp3=35:"

Also, make sure to guarantee that your ls command has the --color option enabled. I usually use something like:

alias ls='ls --color=auto'

Purple color is "35". The other basic colors are:

0   = default colour
1   = bold
4   = underlined
5   = flashing text
7   = reverse field
40  = black background
41  = red background
42  = green background
43  = orange background
44  = blue background
45  = purple background
46  = cyan background
47  = grey background
100 = dark grey background
101 = light red background
102 = light green background
103 = yellow background
104 = light blue background
105 = light purple background
106 = turquoise background

I wanted to achieve the exact same thing to use for git directory listings as well.

My solution is to add a hook in Z shell ( add-zsh-hook chpwd git-alias ) that calls the function git-alias when I change directories. The function git-alias defines, based on whether it's a git directory, the functionality of ll .

function git-alias {
    # Let ll depend on the current directory
    if git rev-parse --git-dir > /dev/null 2>&1; then
        # Make sure ll has no alias assigned
        alias ll='ls' && unalias ll
        function ll {
            ls $@ -lF|grep --color=never -e '/$' # directories
            ls $@ -lQ|grep -f <(git ls-files -cdmoi --exclude-standard)|sed -e "s/\(.*\) \"\(.*\)\"$/\1 ${fg[dgray]}\2 (ignored)$reset_color/" # ignored
            ls $@ -l|grep --color=never -f <(git ls-files -c 2>/dev/null) # cached
            ls $@ -lQ|grep -f <(git ls-files -m 2>/dev/null)|sed -e "s/\(.*\) \"\(.*\)\"$/\1 ${fg[blue]}✎ \2$reset_color/" # modified
            ls $@ -lQ|grep -f <(git ls-files -o --exclude-standard 2>/dev/null)|sed -e "s/\(.*\) \"\(.*\)\"$/\1 ${fg[blue]}★ \2$reset_color/" # new
            git ls-files -d 2>/dev/null|sed -e "s/^\(.*\)$/Deleted: ${fg[red]}✗ \1$reset_color/" # deleted
        }
    else
        alias ll='ls -lF'
    fi
}

This will return something like:

示例输出

It is still not perfect (eg, note the double entry for the file 'LICENSE' and the fixed ordering of files and folders), but it's the best I could achieve.

I've come up with another approximate solution:

tree | sed -f <(git ls-files | awk -F/ '{ print "s/" $NF "/\033[32m\\0\033[0m/" }')

It gets the list of all tracked files from git and creates a sed command for each one that wraps the filename in color escape sequences.

There are some deficiencies:

  • The coloring is based on the filename not the whole path. If two files in different directories have the same name and one is tracked while the other one is not, both are colored.

  • Actually it's even worse because even a part of the filename is colored. If the file a is tracked every a is colored. This could probably be fixed by matching the whole line in the sed command.

  • Directories are not colored (unless they have the same name as a tracked file; see above). This might be improved by using the --directory flag of git ls-files

  • probably more...

I'm using tree instead of ls which makes the issue with directories less problematic (because I can see if it contains tracked files). But you can use ls in the same way of course.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM