steve
steve

Reputation: 109

using awk and stat in one line to print values of stat

Below is the script which I'm trying to run. I cannot use stat inside awk.

cat /etc/passwd | awk 'BEGIN{FS=":"}{print $6 }' | (stat $6 | sed -n '/^Access: (/{s/Access: (\([0-9]\+\).*$/\1/;p}' })'

My desired output should be like this:

 /root 0550 
 /bin  0777
 /sbin 0777

I'm able to write the script using while or for.. but I want all the script to be in one line without loop.

Upvotes: 1

Views: 783

Answers (5)

Tom Hale
Tom Hale

Reputation: 46795

If awk is not mandatory:

stat -c '%n %#8a' <pathnames>

Also look at stat --printf, and --terse which prints a bunch of stuff on one line.

Upvotes: 0

James Brown
James Brown

Reputation: 37404

GNU awk has a sample extension filefuncs which has stat function. Below is based on sample code from its documentation:

$ echo /tmp | awk -F: '                           # testing with echo
@load "filefuncs";                                # enable extension
{
    ret = stat($1,fdata)                          # stat the file
    if (ret < 0)                                  # if file not exists
        printf("could not stat %s: %s\n",file, ERRNO) > "/dev/stderr"
    printf "%s %o\n",fdata["name"],fdata["mode"]  # print name and mode 16 bit
}' 
/tmp 41777

If you want to try that, replace the $1 with $6 and use it like awk '{...}' /etc/passwd You also may need to set shell variable AWKLIBPATH for the extension.

Upvotes: 0

melpomene
melpomene

Reputation: 85767

This would probably be a lot easier / faster if you do it all in perl:

perl -we 'while (@pw = getpwent) { $d = $pw[7]; @st = stat $d or do { warn "$d: $!\n"; next }; printf "%s %s %04o\n", $pw[0], $d, $st[2] & 07777 }'

Advantages:

  • no need to parse /etc/passwd manually
  • no need to spawn external processes, especially not one extra process per line
  • no need to reparse the output from stat
  • easy and flexible output formatting with printf

Upvotes: 1

tink
tink

Reputation: 15214

This should work?

 awk 'BEGIN{FS=":"}{cmd="stat -c\"'%a'\" "$6 ; cmd  | getline perm; close(cmd); printf "%s\t%s\n",$6,perm }' /etc/passwd

Edit 1: A brief explanation:

BEGIN{
  FS=":"  # set field separator 
}
{
  cmd="stat -c\"'%a'\" "$6 ; # define stat as a command w/ only perms as output
  cmd  | getline perm; # capture those perms for the current $6
  close(cmd);  # close the pipe, good practice to get into
  printf "%s\t%s\n",$6,perm # print the directory name and the correlated perms
}

Upvotes: 1

karakfa
karakfa

Reputation: 67507

of course $6 doesn't mean what you think outside of awk, you can do instead

$ awk -F: '{print $6}' /etc/passwd | xargs -n1 stat | sed  ...

Upvotes: 0

Related Questions