Linux – Octal representation of file/folder permissions using awk

awkbashfile-permissionslinux

We have various of machines here with all sorts of hardware and Operating Systems, most of them do regular tasks with bash that an agent executes.
However it came to my attention that some Solaris machines we own do not have stat util, and adding it would be a problem that might take time (ironic)

Meanwhile I was trying to imitate one sisyphean task which stat did in a magnificent way:
return the file permissions in Octal

I found some old example which prints the regular permissions in Octal – rwx, but not for the "special" permissions – sticky group, sticky user, etc

My basic method was this : first calculate the special bits Octal value and then add the regular 'rwx', but it doesn't seem to work well

ls -lah $file  | awk '{k=0;for(i=0;i<=8;i++) {if (substr($1,i+2,1)~/[s]/) k += ((substr($1,i+2,1)~/[s]/)*2^9);else k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));}if (k)printf("%0o ",k);}'


ls -lah $file  | awk '{k=0;for(i=0;i<=8;i++){k+=((substr($1,i+2,1)~/[rwxs]/)*2^(8-i));printf("%0o\n",k)}if(k)printf("%0o ",k);}'

can anyone hint me what would be a good solution ?

Best Answer

This should handle any set of permissions including sticky, setuid and setgid ("s" stands for "set" rather than "sticky" which is "t"). Leading zeros are printed.

ls -lahd "$file" | awk '{k = 0; for (g=2; g>=0; g--) for (p=2; p>=0; p--) {c = substr($1, 10 - (g * 3 + p), 1); if (c ~ /[sS]/) k += g * 02000; else if (c ~ /[tT]/) k += 01000; if (c ~ /[rwxts]/) k += 8^g * 2^p} if (k) printf("%05o ", k)}'

Here it is on multiple lines for readability:

awk '{k = 0; 
      for (g=2; g>=0; g--) 
          for (p=2; p>=0; p--) {
              c = substr($1, 10 - (g * 3 + p), 1); 
              if (c ~ /[sS]/) 
                  k += g * 02000; 
              else 
                  if (c ~ /[tT]/) 
                      k += 01000; 
              if (c ~ /[rwxts]/) 
                  k += 8^g * 2^p
      } 
      if (k) {
          printf("%05o ", k); 
     }'

Demo:

$ touch foo
$ chmod 7654 foo
$ ls -l foo
-rwSr-sr-T 1 user user 0 2012-01-29 13:21 foo
$ ls -l foo | awk '...'
07654