Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Say I have the following output from ls -l:

drwxr-xr-x 2 root root 4096 Apr  7 17:21 foo

How can I automatically convert this to the format used by chmod?

For example:

$ echo drwxr-xr-x | chmod-format
755

I'm using OS X 10.8.3.

share|improve this question
1  
Much easier with stat. Do you have it? (It's a GNU tool, so mostly available on Linux, not on Unix.) –  manatwork Apr 7 '13 at 15:55
    
@manatwork stat foo gives 16777219 377266 drwxr-xr-x 119 Tyilo staff 0 4046 "Apr 7 17:49:03 2013" "Apr 7 18:08:31 2013" "Apr 7 18:08:31 2013" "Nov 25 17:13:52 2012" 4096 0 0 /Users/Tyilo. I don't see 755 in it. –  Tyilo Apr 7 '13 at 16:08

7 Answers 7

up vote 3 down vote accepted

Some systems have commands to display the permissions of a file as a number, but unfortunately, nothing portable.

zsh has a stat (aka zstat) builtin in the stat module:

zmodload zsh/stat
stat -H s some-file

Then, the mode is in $s[mode] but is the mode, that is type + perms.

If you want the permissions expressed in octal, you need:

perms=$(([##8] s[mode] & 8#7777))

BSDs (including Apple OS/X) have a stat command as well.

mode=$(stat -f %p some-file)
perm=$(printf %o "$((mode & 07777))"

GNU find (from as far back as 1990 and probably before) can print the permissions as octal:

find some-file -prune -printf '%m\n'

Later (2001, long after zsh stat (1997) but before BSD stat (2002)) a GNU stat command was introduced with again a different syntax:

stat -c %a some-file

Long before those, IRIX already had a stat command (already there in IRIX 5.3 in 1994) with another syntax:

stat -qp some-file

Again, when there's no standard command, the best bet for portability is to use perl:

perl -e 'printf "%o\n", (stat shift)[2]&07777' some-file
share|improve this answer

On Mac OS X (10.6.8) you have to use stat -f format (because it is actually NetBSD / FreeBSD stat).

# using Bash

mods="$(stat -f "%p" ~)"    # octal notation
mods="${mods: -4}"
echo "$mods"

mods="$(stat -f "%Sp" ~)"  # symbolic notation
mods="${mods: -9}"
echo "$mods"

To just translate a symbolic permission string produced by ls -l into octal (using only shell builtins) see: showperm.bash.

# from: showperm.bash
# usage: showperm modestring
#
# example: showperm '-rwsr-x--x'
share|improve this answer

You can ask GNU stat to output the permissions in octal format by using the -c option. From man stat:

       -c  --format=FORMAT
              use the specified FORMAT instead of the default; output a
              newline after each use of FORMAT
⋮
       %a     access rights in octal
⋮
       %n     file name

So in your case:

bash-4.2$ ls -l foo
-rw-r--r-- 1 manatwork manatwork 0 Apr  7 19:43 foo

bash-4.2$ stat -c '%a' foo
644

Or you can even automate it by formatting stat's output as valid command:

bash-4.2$ stat -c "chmod %a '%n'" foo
chmod 644 'foo'

bash-4.2$ stat -c "chmod %a '%n'" foo > setpermission.sh

bash-4.2$ chmod a= foo

bash-4.2$ ls -l foo
---------- 1 manatwork manatwork 0 Apr  7 19:43 foo

bash-4.2$ sh setpermission.sh 

bash-4.2$ ls -l foo
-rw-r--r-- 1 manatwork manatwork 0 Apr  7 19:43 foo

The above solution will also work for multiple files if using a wildcard:

stat -c "chmod -- %a '%n'" -- *

Will work correctly with file names containing whitespace characters, but will fail on file names containing single quotes.

share|improve this answer
1  
My stat doesn't have a -c option. I'm using OS X 10.8.3. –  Tyilo Apr 7 '13 at 17:15
    
Thanks for the information, @Tyilo. And sorry, I can not help with OS X's tools. –  manatwork Apr 8 '13 at 6:25
    
Try reading manpage^W^W^W stat(1) on Mac OS X have -f flag for specifying output format, e.g. stat -f 'chmod %p "%N"' –  gelraen Apr 8 '13 at 13:56

An alternative, if you want to save the permissions away, to restore them later on, or on a different file is to use setfacl/getfacl, and it will also restore (POSIX-draft) ACLs as a bonus.

getfacl some-file > saved-perms
setfacl -M saved-perms some-other-file

(on Solaris, use -f instead of -M).

However, though they are available on some BSDs, they are not on Apple OS/X where the ACLs are manipulated with chmod only.

share|improve this answer

If your goal is to take permissions from one file and give them to another as well, GNU chmod already has a "reference" option for that.

share|improve this answer
    
The OP mentioned he was on Apple OS/X, so chmod will not be the GNU chmod there. –  Stéphane Chazelas Apr 7 '13 at 21:59
    
Ah yeah I'm seeing the comment on the other answer where they say their platform. Mine isn't the only one mentioning GNU though and you can get GNU Utilities on Mac OS X –  Joel Davis Apr 7 '13 at 22:27

I once came up with:

chmod_format() {
  sed 's/.\(.........\).*/\1/
    h;y/rwsxtSTlL-/IIIIIOOOOO/;x;s/..\(.\)..\(.\)..\(.\)/|\1\2\3/
    y/sStTlLx-/IIIIIIOO/;G
    s/\n\(.*\)/\1;OOO0OOI1OIO2OII3IOO4IOI5IIO6III7/;:k
    s/|\(...\)\(.*;.*\1\(.\)\)/\3|\2/;tk
    s/^0*\(..*\)|.*/\1/;q'
}

(more as an exercise in sed style than a legible script...).

$ echo 'drwSr-sr-T' | chmod_format
7654
share|improve this answer

Here is a script, which does exactly that:

#!/usr/bin/env bash
input="$(cat)"
for i in {0..2}; do
    sum=0
    for j in {0..2}; do
        index=$(($i * 3 + $j + 1))
        char=${input:$index:1}
        if [[ "$char" != "-" ]]; then
            value=$((2 ** (2 - $j)))
            sum=$(($sum + $value))
        fi
    done
    echo -n $sum
done

echo
share|improve this answer
    
Only works if only the first 9 bits are set, not for any mode above 0777. –  Stéphane Chazelas Apr 7 '13 at 17:14
    
@StephaneChazelas I didn't know that there was modes above 0777. –  Tyilo Apr 7 '13 at 17:17
    
Check /tmp, /bin/su, /usr/bin/wall. That's the sStTlL flags in ls -l output. –  Stéphane Chazelas Apr 7 '13 at 17:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.