How to color output columns of ls

bashls

Title kind of says it all: I would like to get those neat colored columns of the output of something like ls -al, say, as in 10basetom’s answer to this question.

Screenshot of syntax-highlighted code snippet from linked answer

Best Answer

This is doable with awk. Unfortunately, since the format of ls -l is unspecified, it is not possible to come up with a solution that will work on every system so some adjustment of which colour to use for which column will be necessary on some systems.


First off, we want to preserve the original spaces used by ls -l. Otherwise, the column alignment will be incorrect. We can do this with the FPAT option, thanks to this SO answer:

ls -la | awk '
    BEGIN {
        FPAT = "([[:space:]]*[^[:space:]]+)";
        OFS = "";
    }

In awk, each positional param ($1, $2, etc.) refers to one field, i.e. one column on the current row. What the FPAT option above did is redefine each field to include all preceding spaces, so when you print it back out it keeps the spaces so the columns stay in the same position.

Now we can simply edit each field to insert the colour code, and then print the edited output:

    {
        $2 = "\033[31m" $2 "\033[0m";
        $3 = "\033[36m" $3 "\033[0m";
        $4 = "\033[36m" $4 "\033[0m";
        $5 = "\033[31m" $5 "\033[0m";
        $6 = "\033[36m" $6 "\033[0m";
        $7 = "\033[36m" $7 "\033[0m";
        $8 = "\033[31m" $8 "\033[0m";
        print
    }
'

Notice that each column is reset back to default (the 0 between the [ and m) afterwards. If you want the colour to run across multiple columns, you can omit that code. Personally, I prefer to specify each column independently.


You can define the a reusable command in your .bashrc. For example:

lsc() {
    ls -la | awk '
        BEGIN {
            FPAT = "([[:space:]]*[^[:space:]]+)";
            OFS = "";
        }
        {
            $2 = "\033[31m" $2 "\033[0m";
            $3 = "\033[36m" $3 "\033[0m";
            $4 = "\033[36m" $4 "\033[0m";
            $5 = "\033[31m" $5 "\033[0m";
            $6 = "\033[36m" $6 "\033[0m";
            $7 = "\033[36m" $7 "\033[0m";
            $8 = "\033[31m" $8 "\033[0m";
            print
        }
    '
}

You may need to restart your bash session (or run source ~/.bashrc) for this function definition to run.

From here, you can just call lsc, which should give you the output you desire:

Screenshot of coloured output