Home > other >  What is the right awk regex to match folder, hidden folder, normal file, so I can colorize them usin
What is the right awk regex to match folder, hidden folder, normal file, so I can colorize them usin

Time:11-02

ls -lhAXF --group-directories-first "$@" | awk '
    BEGIN {
        FPAT = "([[:space:]]*[^[:space:]] )";
    } {
        $1 = "\033[1m" "\033[31m" $1 "\033[0m";
        $2 = "\033[1m" "\033[32m" $2 "\033[0m";
        $3 = "\033[1m" "\033[33m" $3 "\033[0m";
        $4 = "\033[34m" $4 "\033[0m";
        $5 = "\033[1m" "\033[35m" $5 "\033[0m";
        $6 = "\033[1m" "\033[36m" $6 "\033[0m";
        $7 = "\033[1m" "\033[37m" $7 "\033[0m";
        $8 = "\033[1m" "\033[33m" $8 "\033[0m";
        print
    }'

link to the output

what is the correct syntax to achieve the following:

  1. color normal directory to red
  2. color hidden directory to blue
  3. color regular file to green

what i know:

  1. match normal directory with regex like any word ending with '/' inside column $9
  2. match hidden directory with regex like any word starting with '.' inside column $9
  3. match regular file with regex like the rest of line that doesn't match ending with '/' and doesn't match starting with '.'
  4. i know something like: awk '$9 ~ /something/' to match the right column

but where to put the syntax, and what is the syntax look like?

i want to colorize the result of the regex after it matches using escape code like "\033[32m"

CodePudding user response:

As explained in comments parsing the output of ls is not recommended; ls is for humans only. But if you absolutely want to do it this way you can try the following:

ls -lhAXF --group-directories-first "$@" | awk '
  BEGIN {FPAT = "([^[:space:]] [[:space:]]*)"}
  {if($1 ~ /^d/ && $9 ~ /^\./) $9 = "\033[31m" $9
   else if($1 ~ /^d/) $9 = "\033[32m" $9
   else $9 = "\033[33m" $9
   for(i=1;i<NF;i  ) $i = sprintf("\033[3%dm%s", i, $i)
   $1 = "\033[1m" $1
   $NF = $NF "\033[0m"
   print}'

We first redefine the fields as word-spaces instead of spaces-word because it makes the detection of hidden directories, non-hidden directories and non-directories easier: the relevant parts are now at the beginning of the field:

  • $1 ~ /^d/ => directory
  • $9 ~ /^\./ => hidden

We also simplify a bit by suppressing useless intermediate ANSI codes and by using a for loop to prepend the ANSI colour code to each field.

The rest is straightforward. We first prepend the colour ANSI escape codes to $9 (name field) based on the type. Next, we prepend the colour ANSI escape codes to the other fields, based on the field index. Finally, we prepend the bold code to $1 and the reset code to the last field, and we print.


Edit by Ed Morton: here is the above script pretty-printed by gawk -o- for improved legibility:

BEGIN {
        FPAT = "([^[:space:]] [[:space:]]*)"
}

{
        if ($1 ~ /^d/ && $9 ~ /^\./) {
                $9 = "\033[31m" $9
        } else if ($1 ~ /^d/) {
                $9 = "\033[32m" $9
        } else {
                $9 = "\033[33m" $9
        }
        for (i = 1; i < NF; i  ) {
                $i = sprintf("\033[3%dm%s", i, $i)
        }
        $1 = "\033[1m" $1
        $NF = $NF "\033[0m"
        print
}

CodePudding user response:

You are trying to test for the trailing slashes applied to directory names by ls -F.

What you are looking for is something like this:

BEGIN {
    red = "\033[31m" # dir
    green = "\033[32m" # file
    blue = "\033[36m" # hidden dir
    reset = "\033[0m"
}

{
    if ($9 ~ /\/$/) {
        if ($9 ~ /^\./) {
            $9 = blue $9 reset
        }
        else {
            $9 = red $9 reset
        }
    }
    else {
        $9 = green $9 reset
    }
}

But it breaks if file names contain spaces/tabs.

You could test the first character of column 1 (of ls -l) instead (d or -)… But you’d be better off looking in to utilities like stat and find.

  • Related