229

Is it possible when listing a directory to view numerical unix permissions such as 644 rather than the symbolic output -rw-rw-r--

Thanks.

Jon Winstanley
  • 22,404
  • 20
  • 73
  • 111

9 Answers9

391

it almost can ..

 ls -l | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/) \
             *2^(8-i));if(k)printf("%0o ",k);print}'
Jean-François Fabre
  • 131,796
  • 23
  • 122
  • 195
miku
  • 172,072
  • 46
  • 300
  • 307
  • 33
    For creating it as an alias (example below: 'cls' command), use: ```alias cls="ls -l | awk '{k=0;for(i=0;i<=8;i++)k+=((substr(\$1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf(\"%0o \",k);print}'"``` – Melroy van den Berg Mar 06 '14 at 16:15
  • 6
    I copy and pasted the line from danger89 and found that strangely the output began with %0..o per line, instead of say 755. If anyone else comes across this, the cause appears to be a hidden character between the 0 and o. Once deleted the command is set up nicely. Cheers! – Donna Mar 09 '14 at 17:31
  • I think there is an calculation issue. After `chmod 777 dir` your command prints permissions as `767` – Julian F. Weinert Apr 24 '14 at 10:55
  • As Donna mentions, there is a funny character (or 2) between the 0 and o, also, weirdly it looks like SO is adding it... – nbsp Nov 17 '14 at 19:49
  • Does anyone have a working alias for this command? awk runtime error involving "%0o " on a debian derivative – cremefraiche Oct 18 '15 at 00:01
  • 4
    This fails to recognize bits t and s. You should use the 'stat' command to get the file permission information. Calculating it by hand will lead to errors! – Evan Langlois Nov 09 '15 at 06:28
  • @danger89 `awk` actually preserves the color if you use the `ls` option `--color`, too. – Geremia Feb 28 '16 at 03:21
  • Nice but doesnt work in www.codeanywhere.com virtual machine terminal. awk: cmd. line:3: awk: cmd. line:3: ^ unexpected newline or end of string awk: cmd. line:3: *2^(8-i));if(k)printf("%0o ",k);print} awk: cmd. line:3: ^ syntax error awk: cmd. line:3: *2^(8-i));if(k)printf("%0o ",k);print} awk: cmd. line:3: ^ syntax error awk: cmd. line:3: *2^(8-i));if(k)printf("%0o ",k);print} awk: cmd. line:3: ^ syntax error – Kangarooo Mar 24 '16 at 23:15
186

Closest I can think of (keeping it simple enough) is stat, assuming you know which files you're looking for. If you don't, * can find most of them:

/usr/bin$ stat -c '%a %n' *
755 [
755 a2p
755 a2ps
755 aclocal
...

It handles sticky, suid and company out of the box:

$ stat -c '%a %n' /tmp /usr/bin/sudo
1777 /tmp
4755 /usr/bin/sudo
JB.
  • 37,635
  • 10
  • 80
  • 106
  • 27
    This works great under Linux, I found `stat -f '%A %N' *` does the same thing on a mac (FreeBSD) – reevesy May 29 '14 at 12:07
  • 2
    I guess the argument is that `stat` is not `ls` therefore this is not the correct answer. However, I believe this is the correct answer in context of the desired output. If `awk` is permitted in a pipe, then `find` should be permitted where `stat` is called in `-exec`; then you can use `stat` directly without `*` – javafueled Mar 04 '15 at 14:29
  • 2
    This is much better shorter and 100% working on any system – Kangarooo Mar 24 '16 at 23:15
  • If you want to use stat to see the rights recursively, under bash, use `stat -c '%a %n' * **/*`. – Denis Chevalier Aug 11 '17 at 13:37
  • according to `man stat -c or --format`: `%a access rights in octal (note '#' and '0' printf flags), %n file` – Timo Jul 12 '21 at 13:28
74

you can just use GNU find.

find . -printf "%m:%f\n"
ghostdog74
  • 307,646
  • 55
  • 250
  • 337
48

You can use the following command

stat -c "%a %n" *

Also you can use any filename or directoryname instead of * to get a specific result.

On Mac, you can use

stat -f '%A %N' *
Mohd Abdul Mujib
  • 11,978
  • 8
  • 59
  • 84
  • 1
    Didn't work for me. `stat: illegal option -- c` `usage: stat [-FlLnqrsx] [-f format] [-t timefmt] [file ...]` – rschwieb Mar 14 '16 at 19:25
  • 1
    works on ubuntu 14.04.. to never have to remember this I've added an alias in my .bashrc: alias xxx="stat -c '%a %n' *" – faebster Apr 29 '16 at 01:52
  • 2
    Helpful! How you dig it out the %A which not even shows up in man of stat on Mac? – igonejack Jan 17 '18 at 03:43
  • 1
    It actually is a FreeBSD command, and Mac just happens to be built upon that using it as upper kernel. – Mohd Abdul Mujib Jan 17 '18 at 04:44
  • If we only use the information presented in `man stat` on macOS 10.14.4, then the command should be `stat -f "%Lp %N" *`. `%Lp` appears to print the same thing as `%A`. – Cesar Andreu Apr 03 '19 at 07:03
22

Use this to display the Unix numerical permission values (octal values) and file name.

stat -c '%a %n' *

Use this to display the Unix numerical permission values (octal values) and the folder's sgid and sticky bit, user name of the owner, group name, total size in bytes and file name.

stat -c '%a %A %U %G %s %n' *

enter image description here

Add %y if you need time of last modification in human-readable format. For more options see stat.

Better version using an Alias

Using an alias is a more efficient way to accomplish what you need and it also includes color. The following displays your results organized by group directories first, display in color, print sizes in human readable format (e.g., 1K 234M 2G) edit your ~/.bashrc and add an alias for your account or globally by editing /etc/profile.d/custom.sh

Typing cls displays your new LS command results.

alias cls="ls -lha --color=always -F --group-directories-first |awk '{k=0;s=0;for(i=0;i<=8;i++){;k+=((substr(\$1,i+2,1)~/[rwxst]/)*2^(8-i));};j=4;for(i=4;i<=10;i+=3){;s+=((substr(\$1,i,1)~/[stST]/)*j);j/=2;};if(k){;printf(\"%0o%0o \",s,k);};print;}'"

Alias is the most efficient solution

Folder Tree

While you are editing your bashrc or custom.sh include the following alias to see a graphical representation where typing lstree will display your current folder tree structure

alias lstree="ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/   /' -e 's/-/|/'"

It would display:

   |-scripts
   |--mod_cache_disk
   |--mod_cache_d
   |---logs
   |-run_win
   |-scripts.tar.gz
Erick Gonzalez
  • 333
  • 3
  • 6
19

@The MYYN

wow, nice awk! But what about suid, sgid and sticky bit?

You have to extend your filter with s and t, otherwise they will not count and you get the wrong result. To calculate the octal number for this special flags, the procedure is the same but the index is at 4 7 and 10. the possible flags for files with execute bit set are ---s--s--t amd for files with no execute bit set are ---S--S--T

ls -l | awk '{
    k = 0
    s = 0
    for( i = 0; i <= 8; i++ )
    {
        k += ( ( substr( $1, i+2, 1 ) ~ /[rwxst]/ ) * 2 ^( 8 - i ) )
    }
    j = 4 
    for( i = 4; i <= 10; i += 3 )
    {
        s += ( ( substr( $1, i, 1 ) ~ /[stST]/ ) * j )
        j/=2
    }
    if ( k )
    {
        printf( "%0o%0o ", s, k )
    }
    print
}'  

For test:

touch blah
chmod 7444 blah

will result in:

7444 -r-Sr-Sr-T 1 cheko cheko   0 2009-12-05 01:03 blah

and

touch blah
chmod 7555 blah

will give:

7555 -r-sr-sr-t 1 cheko cheko   0 2009-12-05 01:03 blah
user224243
  • 399
  • 1
  • 5
5

You don't use ls to get a file's permission information. You use the stat command. It will give you the numerical values you want. The "Unix Way" says that you should invent your own script using ls (or 'echo *') and stat and whatever else you like to give the information in the format you desire.

Evan Langlois
  • 3,553
  • 2
  • 18
  • 18
2

Building off of the chosen answer and the suggestion to use an alias, I converted it to a function so that passing a directory to list is possible.

# ls, with chmod-like permissions and more.
# @param $1 The directory to ls
function lls {
  LLS_PATH=$1

  ls -AHl $LLS_PATH | awk "{k=0;for(i=0;i<=8;i++)k+=((substr(\$1,i+2,1)~/[rwx]/) \
                            *2^(8-i));if(k)printf(\"%0o \",k);print}"
}
Community
  • 1
  • 1
Curtis Blackwell
  • 2,981
  • 1
  • 25
  • 45
  • Doesn't work for some UNIX: `ls: ERROR: Illegal option -- H` then `usage: ls -1ACFLRTabcdfgilmnopqrstux -W[sv] [files]` and `awk: cmd. line:2: fatal: file '/usr/include' is a directory` – kbulgrien Oct 06 '20 at 18:04
0

Considering the question specifies UNIX, not Linux, use of a stat binary is not necessary. The solution below works on a very old UNIX, though a shell other than sh (i.e. bash) was necessary. It is a derivation of glenn jackman's perl stat solution. It seems like an alternative worth exploring for conciseness.

$ alias lls='llsfn () { while test $# -gt 0; do perl -s -e \
  '\''@fields = stat "$f"; printf "%04o\t", $fields[2] & 07777'\'' \
    -- -f=$1; ls -ld $1; shift; done; unset -f llsf; }; llsfn'
$ lls /tmp /etc/resolv.conf
1777    drwxrwxrwt   7 sys      sys       246272 Nov  5 15:10 /tmp
0644    -rw-r--r--   1 bin      bin           74 Sep 20 23:48 /etc/resolv.conf

The alias was developed using information in this answer

The whole answer is a modified version of a solution in this answer

kbulgrien
  • 4,179
  • 2
  • 23
  • 40