LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   reading unix file permissions into a bash array for processing (http://www.linuxquestions.org/questions/programming-9/reading-unix-file-permissions-into-a-bash-array-for-processing-847720/)

dazdaz 12-01-2010 11:58 AM

reading unix file permissions into a bash array for processing
 
Hi,

I would like to read unix file permissions into a bash array for processing but tbh i have no idea how to do this. Then I will check for each individual access right l, d, x etc

I'd be greatful for some pointers.

Thanks

tuxdev 12-01-2010 12:33 PM

Use "stat". It kinda sounds like you want to parse the output of ls, but that's a bad idea

dazdaz 12-01-2010 01:13 PM

Hmm this is on Solaris which does'nt have stat afaik. What would you suggest ? Use an array in BASH / awk ? How do you read the first 7 characters into an array using awk...

grail 12-01-2010 07:04 PM

Ok. So it is homework and appears that the do wish you to use 'ls -l' (ie the reference to first 7 characters)

Maybe you could show what you have tried and where you are getting stuck?

By the LQ rules no one will do the work for you (as you won't learn that way), but we are more than happy to guide you when stuck :)

dazdaz 12-02-2010 01:15 PM

Hi,

I have read in the ls attributes of a file into an array using nawk. I think that using awk might be better than bash for this task...

I think I can see how it would work... All 9 byte's for the permission could be read into another array,
and then processed however I am not entirely sure if I need substr to provide the offset or if there is another method.

If the filename has spaces then this script won't print the full filename, so I need to assign array[filename] $9 to the end of the line. How can I do that in awk ?
I have never seen a filename with a newline... i am not sure how to factor that in but i realise that it's possible.

PS. Coincidentally the script below makes a cleaner formatted Solaris ls, than the native output :-)


Code:

/usr/bin/ls -l | nawk ' {array["perms" ++i]=$1};
                        {array["links" i]=$2};
                        {array["user" i]=$3};
                        {array["group" i]=$4};
                        {array["size" i]=$5};
                        {array["month" i]=$6};
                        {array["day" i]=$7};
                        {array["year" i]=$8};
                        {array["filename" i]=$9};
# END {for (j=1;j<=i;j++) {printf "%7s %4s %10s %10s %10s %4s %4s %5s %-20s\n", array["perms" j],array["links" j],array["user" j],array["group" j],array["size" j],array["month" j],array["day" j],array["year" j],array["filename" j]}}'

END {for (j=1;j<=i;j++) {for (count=1; i<=9; i++) p0=substr(array["perms"],count,1} if p0=="d" then printf "Directory %7s %4s %10s %10s %10s %4s %4s %5s %-20s\n", array["perms" j],array["links" j],array["user" j],array["group" j],array["size" j],array["month" j],array["day" j],array["year" j],array["filename" j]}}'


grail 12-02-2010 11:17 PM

So you lost me here?? Why have you done all the extra items? I thought we were looking at the permissions?

I am now not sure what you are looking to achieve or have you now found what you are looking for?

dazdaz 12-03-2010 02:49 PM

Hi Grail, how are you. Thanks for your reply.

Let me explain some more :-))

If a directory, the print an ansi code (colour red for example), if a symbolic link then print blue.

I'm still not confident with the correct awk to process each permission.

grail 12-04-2010 02:58 AM

So I am guessing (as have not worked on Solaris) that your ls does not have a colour option by default, but you are looking to make your own colourized ls output?

If this is the case maybe we do not need awk at all?? All you really need to know is the first letter at the beginning of permissions (ie d, l, -, etc) and then use a case statement
to apply the appropriate colour.

You could still probably do in awk as well.

Something like:
Code:

#!/bin/bash

NORMAL='\e[0;37m'

while read -r LINE
do
    FILE=false

    case ${LINE:0:1} in
        -)  COLOR=$NORMAL;FILE=true;;
        d)  COLOR='\e[0;34m';;
        l)  COLOR='\e[1;36m';;
        *)  COLOR=$NORMAL;;
    esac

    if $FILE && [[ ${LINE:0:9} =~ x ]]
    then
      COLOR='\e[1;32m'
  fi

    echo -e "$COLOR$LINE$NORMAL"
done< <(ls -l --color=no)

Probably needs tidy up to cope with more things, but you get the idea.

dazdaz 12-04-2010 08:12 AM

Hi. Solaris does not have a colour'ised ls with the OS. There is GNU ls, but it's not always possible to install it (company rules/regulations), and it's nice to have this in a shell function, so any user can run use it or modify as they like.

I like your solution, it's clean, neat and just works (I tested that it works on Solaris 10)

I have been trying to finish this in awk as a learning exercise. I'm getting much closer but not quite there. Right now it prints upto the first directory or 10th file and then quits which is'nt intended. Would you have any suggestions or pointers ?

Code:

#!/bin/bash

/bin/ls -l --color=no | gawk ' {array["perms" ++i]=$1};
                        {array["links" i]=$2};
                        {array["user" i]=$3};
                        {array["group" i]=$4};
                        {array["size" i]=$5};
                        {array["month" i]=$6};
                        {array["day" i]=$7};
                        {array["year" i]=$8};
                        {array["filename" i]=$9};
END {
        for (j=1;j<=i;j++) {
                for (i=1;i<11;i++) {
                        perm=substr(array["perms" j],i,1)
#                      printf "%s %s\n", perm, array["filename" j]
                        if ( perm ~ /d/ ) {
                                colour="\033[0;34m" ; break }
                        if ( perm ~ /l/ ) {
                                colour="\033[0;36m" ; break }
                        else if ( perm ~ /s/ ) {
                                colour="\033[0;36m" ; break }
                        else
                                colour="\033[0;37m"
                                }
                                printf "%s%7s %4s %10s %10s %10s %4s %4s %5s %-20s\n", colour, array["perms" j],array["links" j],array["user" j],array["group" j],array["size" j],array["month" j],array["day" j],array["year" j],array["filename" j]
                                printf "\033[0;37m"
                        }
}'


grail 12-04-2010 10:56 AM

So you are either going to love or hate this idea ... but here goes, this is how the awk script would look for me:
Code:

#!/usr/bin/awk -f

BEGIN{
    DIR="\033[0;34m"
    EXE="\033[0;32m"
    LINK="\033[0;36m"
    SOCK="\033[0;36m"
    NORM="\033[0;37m"
}

{ colour = NORM }

/^d/{ colour = DIR }
/^l/{ colour = LINK }
/^s/{ colour = SOCK }

$1 ~ /^-.*x/{ colour = EXE }

{ print colour $0 NORM }

Put this in a file called ll.awk and set execution. Run like so to test:
Code:

ls -l --color=no | ./ll.awk
I just find it a little cleaner and easy to change your colours later should you wish :)

dazdaz 12-04-2010 11:12 AM

V. nice, thank you :-)

jlliagre 12-06-2010 04:21 PM

Quote:

Originally Posted by dazdaz (Post 4180380)
Hi. Solaris does not have a colour'ised ls with the OS.

Solaris 11 has it:
http://bugs.opensolaris.org/bugdatab...bug_id=6803941


All times are GMT -5. The time now is 10:58 AM.