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
}'
what is the correct syntax to achieve the following:
- color normal directory to red
- color hidden directory to blue
- color regular file to green
what i know:
- match normal directory with regex like any word ending with '/' inside column $9
- match hidden directory with regex like any word starting with '.' inside column $9
- match regular file with regex like the rest of line that doesn't match ending with '/' and doesn't match starting with '.'
- 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
.