30

After looking at the man page for ls on my system and searching Google, I see there IS a hack of way to use awk or perl to show octal permissions when using ls, but with bash is there anything more native?

Standard output of ls -alh

$ ll
total 0
drwxr-xr-x   5 user  group   170B May 20 20:03 .
drwxr-xr-x  17 user  group   578B May 20 20:03 ..
-rw-r--r--   1 user  group     0B May 20 20:03 example
-rw-r--r--   1 user  group     0B May 20 20:03 example-1
-rw-r--r--   1 user  group     0B May 20 20:03 example-3

Desired output including octal representation of permissions

$ ll
total 0
drwxr-xr-x 1775  5 user  group   170B May 20 20:03 .
drwxr-xr-x 1775 17 user  group   578B May 20 20:03 ..
-rw-r--r-- 1644  1 user  group     0B May 20 20:03 example
-rw-r--r-- 1644  1 user  group     0B May 20 20:03 example-1
-rw-r--r-- 1644  1 user  group     0B May 20 20:03 example-3

(disclaimer: not sure if those octals are exactly right)

Reasoning

I am more familiar with the drwxr-xr-x notation for permissions but sometimes when the dashes fall in odd places I might mis-read it at a quick glance. I'd like to see the octal equivalent as well.

Conversion Ability (question part 2)

I think a long time ago octal permissions might have been limited to 000 - 777 but in recent times there are some things like set-group-ID and sticky that have given us octals with 4 places like 1775. Is it possible to represent every possible permission in octal format? If it is not then I'd better understand why bash's ls command doesn't seem to have this format.

Braiam
  • 35,991
cwd
  • 45,389

3 Answers3

20

You can use the stat command and get roughly what you want:

$ stat -c '%A %a %h %U %G %s %y %n' *
drwxrwxr-x 775 2 saml saml 4096 2013-05-16 22:02:13.230463837 -0400 alsa
drwxrwxr-x 775 31 saml saml 4096 2013-03-26 12:09:20.707827127 -0400 apps
-rw-rw-r-- 664 1 saml saml 43627 2013-05-18 12:28:32.157583577 -0400 autosave.h2song
-rw-rw-r-- 664 1 saml saml 3283 2013-05-18 02:49:41.565154101 -0400 bbbb
drwxrwxr-x 775 4 saml saml 4096 2013-05-03 06:56:50.087842384 -0400 bin
-rw-rw-r-- 664 1 saml saml 4403 2013-05-18 19:20:05.819681196 -0400 blahblah

Here's the cleaned up version if you want it:

$ stat -c '%A %a %h %U %G %s %y %n' *| sed 's/\.[[:digit:]]\+[ ]\+-[[:digit:]]\+/ /'
drwxrwxr-x 775 2 saml saml 4096 2013-05-16 22:02:13  alsa
drwxrwxr-x 775 31 saml saml 4096 2013-03-26 12:09:20  apps
-rw-rw-r-- 664 1 saml saml 43627 2013-05-18 12:28:32  autosave.h2song
-rw-rw-r-- 664 1 saml saml 3283 2013-05-18 02:49:41  bbbb
drwxrwxr-x 775 4 saml saml 4096 2013-05-03 06:56:50  bin
-rw-rw-r-- 664 1 saml saml 4403 2013-05-18 19:20:05  blahblah

Take a look at the stat man page for more format operators that you can use in addtion to the ones above.

References

slm
  • 369,824
  • That looks pretty good - even works with the sticky bit! thanks! wish the file sizes lined up better but its close enough :) – cwd May 21 '13 at 00:47
  • @cwd the file sizes will align just fine if you remove the %h which is what changes the line length. %h is the number of hard links to the file which is not something you need most times you run ls. – terdon May 21 '13 at 01:19
  • Did you mean %s for size, not %B? – Runium May 21 '13 at 01:21
  • @Sukminder, that's what I would've used but I thought he had the size being displayed in bytes in the original question? Isn't that what the 170B is? – slm May 21 '13 at 01:25
  • B, K, M, G would be fine - just human readable is preferable – cwd May 21 '13 at 01:32
  • Yes, he uses -h for ls which gives human. But %B in stat gives block size, %b gives number of %B sized block used, and %s total size in bytes. So bytes would be %B * %b – Runium May 21 '13 at 01:32
  • @Sukminder, my bad, I misread the %b to mean bytes. Thanks for the catch. I'll fix the answer to include %s. – slm May 21 '13 at 01:40
11

I also use stat to get a ls-like output but I use a different approach to format the output: I use TAB as a delimiter (allows for easier parsing afterwards, if needed), format the time via stat and finally filter the output with numfmt (included in GNU coreutils >= 8.21 2013-02-14) to get nice file sizes:

stat --printf="%A\t%a\t%h\t%U\t%G\t%s\t%.19y\t%n\n" * | numfmt --to=iec-i --field=6 --delimiter='     ' --suffix=B

Note the delimiter used for numfmt is also a Tab (to input in terminal hit Ctrl+V then Tab).
This is what the output looks like:

drwxr-xr-x  755 2   don users   4.0KiB  2013-05-17 03:37:02 150905-adwaita-x-dark-light-1.3
drwxr-xr-x  755 8   don users   4.0KiB  2011-10-13 07:30:39 Adwaita Slim
drwxr-xr-x  755 3   don users   4.0KiB  2013-05-17 19:26:41 Away
drwxr-xr-x  755 5   don users   4.0KiB  2013-05-17 03:09:14 elementary
-rw-r--r--  644 1   don users   539KiB  2013-05-10 00:32:14 gdm.jpg
-rw-r--r--  644 1   don users   1.5MiB  2013-05-19 04:30:16 gnome-shell-3.8.2.tar.xz
drwxrwxr-x  775 4   don users   4.0KiB  2013-05-18 18:34:38 gnome-themes-standard-3.8.1
-rw-r--r--  644 1   don users   3.7MiB  2013-05-18 18:30:06 gnome-themes-standard-3.8.1.tar.xz
drwxrwxr-x  775 17  don users   4.0KiB  2013-05-18 18:37:05 gtk+-3.8.2
-rw-r--r--  644 1   don users   14MiB   2013-05-18 18:30:56 gtk+-3.8.2.tar.xz
drwxr-xr-x  755 13  don users   4.0KiB  2013-05-18 02:41:51 MediterraneanNight-2.02
-rw-r--r--  644 1   don users   603B    2013-05-19 20:07:26 python-pytaglib.tar.gz
-rw-r--r--  644 1   don users   442KiB  2013-05-19 00:33:27 Stripes.jpg

Note: as per cwd's comment, on OSX, coreutils commands are gstat and gnumfmt.

Runium
  • 28,811
don_crissti
  • 82,805
  • wow that certainly looks exactly like an ls listing. nice! – cwd May 21 '13 at 01:26
  • 1
    while this looks really good I want it to work with systems that aren't the most cutting edge as well, and numfmt seems to require a pretty new system as I just checked out corutils and 8.21 fairly new and as you mentioned it requires > 8.21 for numfmt. Also on OS X (which is not really linux I know) the stat command seems to be having trouble with the the --printf part. – cwd May 21 '13 at 01:37
  • @cwd: Under OS X, you have -t timefmt, and -f is equivalent to --printf=. At least if I read the man correctly. (No system to test on here). – Runium May 21 '13 at 01:49
  • @Sukminder - you're right about the changes but some of the other flags don't line up as well. I'm going to give up try and install GNU stat (if I can find it in a homebrew repo) because I want it to work the same as it does on the Linux boxes I work with. ( I've already got GNU sed so hopefully I can soon use the same syntax on both systems for stat too). Unfortunately right now coreutils is at 8.21 with homebrew though :( – cwd May 21 '13 at 01:53
  • @don_crissti - thanks! mb update your answer to use the >= instead of just > - also, for others - on OS X the commands from coreutils are gnumfmt and gstat. how odd. thanks! now i have it working on linux and osx! – cwd May 21 '13 at 02:07
  • This doesn't work on my system. I see numfmt, I can't even find that tool in any package for Fedora. I have coreutils 8.5, there isn't any numfmt in that package. – slm May 21 '13 at 02:19
  • Yeah I finally found it. My ancient coreutils doesn't include it @ 8.5. – slm May 21 '13 at 02:30
  • 1
    What is the purpose of the numfmt again? I ignore this part numfmt --to=iec-i --field=6 --delimiter=' ' --suffix=B and the output is the same – MaXi32 Sep 11 '21 at 05:54
  • @MaXi32 the numfmt ... converts the file size - resp. the 6th field separated by a TAB - to a human readable number. || note: you have to replace whatever is between the ' of the --delimiter= with an actual TAB manually! if it is just a space or empty, nothing will be converted. - unfortunately most terminals do not paste an actual TAB and also something like \t or %t does not work as only one character is allowed. – DJCrashdummy Oct 23 '23 at 08:28
1

This awk code transforms the rights from symbol to digit. But it covers only the normal cases (i.e. at least not sStT):

awk '$1 ~ /^[-dsbclp]([-r][-w][-x]){3}[.+]?$/ 
  {for(i=0;i<3;i++) {symbol=substr($1,2+i*3,3); sum=0; 
    if (substr(symbol,1,1) == "r") sum+=4;
    if (substr(symbol,2,1) == "w") sum+=2;
    if (substr(symbol,3,1) == "x") sum+=1;
    printf "%d",sum;}}'

And this produces the output you want:

awk '$1 ~ /^[-dsbclp]([-r][-w][-x]){3}[.+]?$/ 
  {printf "%s ",$1; 
    for(i=0;i<3;i++) {symbol=substr($1,2+i*3,3); sum=0; 
      if (substr(symbol,1,1) == "r") sum+=4;
      if (substr(symbol,2,1) == "w") sum+=2;
      if (substr(symbol,3,1) == "x") sum+=1;
      printf "%d",sum;}
    $1=""; print}'
Hauke Laging
  • 90,279
  • per the question - I see there IS a hack of way to use awk or perl to show octal permissions when using ls, but with bash is there anything more native - just sayin – cwd May 21 '13 at 01:25
  • @cwd bash can do everything I used with awk. – Hauke Laging May 21 '13 at 01:36