Today, I thought I'd put together a little script (written in **ksh**, but easily portable to **sh** or **Perl**) to address a common concern amongst users of most **Unix/Linux**-based systems; how to translate **alpha** permissions (like **-rwxrwxr-x**) to **octal** (like **775**). This issue has been addressed, to some degree by all flavors of ***nix**, in that you can use the **chmod** command either way. For instance, if you had a file with **775** (or **-rwxrwxr-x**) permissions, you could add "**other**" (or "**world**") write permissions to the file by doing:

**chmod 777 FILENAME** or **chmod o+w FILENAME**

Both ways are equally effective and, you might even say that their are some advantages to using one over the other. For instance, with **octal** permissions, to add "**group**" write permissions to a **755** file, you would have to remember to retain the original modes when executing **chmod**. If you just did:

**chmod 070**

It would cause serious issues (**755 becomes 070**)! It's much easier to remember:

**chmod g+w**

Which would add the write permissions for "**group**" ownership and not affect the other bits (**755 becomes 775**)!

One example of a situation where you absolutely "**must**" use alpha notation with **chmod** is an old bug in **Solaris** (that exists even today, in **Solaris 10** - latest patch release), whereby you "**cannot**" set the "**group ID**" bit (more commonly referred to as **setgid**) on a directory with octal notation. For instance:

**xyx.com[/export/home/user] # chmod 2755 bob xyz.com[/export/home/user] # ls -ld bob drwxr-xr-x 2 root other 512 Dec 3 16:34 bob** <--- No Good.

**xyz.com[/export/home/user] # chmod g+s bob**

xyz.com[/export/home/user] # ls -ld bob

drwxr-sr-x 2 root other 512 Dec 3 16:34 bob<--- Now it's working :)

xyz.com[/export/home/user] # ls -ld bob

drwxr-sr-x 2 root other 512 Dec 3 16:34 bob

The only other thing left to explain before we get to the script (assuming you're still reading this and haven't just blown to the bottom already ;) is the common misconception that there are only 3 octal numerics in a file's (or anything's) permissions. This may not be news to most folks, but there are actually 4 octals. The last 3 are the ones that are usually represented; as in 755. The fourth, which is actually the first, is usually an implied 0. For example,

**755**is the same as

**0755**. The first (usually omitted) bit has a potential of

**4**different values (

**0, 1, 2 and 4 or any combination thereof**), just like the rest of them do, although they take on a unique significance.

For the last 3 bits (

**user**,

**group**and

**other**permissions) the translation is the same. They can have values of 0-7 for each.

**000**would equal

**---------**, while

**777**would equal

**rwxrwxrwx**The permissions are compounded by adding the value of the bits. So

**0**results in a "

**---**",

**1**results in "

**--x**",

**2**results in "

**-w-**" and

**4**results in "

**r--**". Compounding them is just a matter of addition. So if the value of the user bit was 6, you could only acheive that result (from your selection of 0, 1, 2 and 4) by adding 4 and 2. By merging the above descriptions,

**6**would have a value of "

**rw-**" (

**4 "r--"**plus

**2 "-w-"**).

The first (usually hidden) bit is reserved for activating the

**setuid**bit (

**value of 4**),

**setgid**bit (

**value of 2**) and

**sticky bit**(

**value of 1**). As always, 0 equals nothing. These bits are special because, although they'll appear as numerals in your 4 bit octal notation, they appear in different places when using alpha notation. The

**setuid**bit (

**Value of 4**) shows up in the "

**user**" permissions as an "

**s**" where the "

**x**" would normally be (

**like rws instead of rwx**). The same is true of the

**setgid**bit (

**Value of 2**), although it shows up in the "

**group**" permissions. The

**sticky bit**(

**Value of 1**) shows up in the "

**other**" permissions as a "

**t**" (

**like rwt instead of rwx**). In a future post, we'll explore how the bit permissions "

**actually**" modify the files and/or directories they are applied to (This differs for all 4 bits, and is another post in itself).

Below is the initial script to convert all of the alpha permissions you'd see (using "

**ls -l**") on any file(s), to their corresponding octal notation. This can more easily be applied in reverse (which is probably why I wrote it this way first). Note that this was also created using what I call "

**brute force scripting**"; the fastest means to an acceptable end. Feel free to doll it up and make it work better for you. As it is, it will accept any option that the standard "

**ls**" would. So, if you called it "

**lso**," you could execute "

**./lso /export/home/user**" or "

**./lso -R /export/home/user**" or just plain "

**./lso**" -- I'll be using this script (since it has a number of different scripting constructs in it) to demonstrate how to port

**shell**scripts to

**Perl**in a future post, also.

Best wishes :)

This work is licensed under a

Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

**#!/bin/ksh**

#

# 2007 - Mike Golvach - eggi@comcast.net

#

# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#

arg=$@

ls -l $arg|awk '{ if ($0 !~ /^$/) print $1 " " $NF}'|grep -v "^total"|while read perms filename

do

if [ $filename = $perms ]

then

print "$filename = Directory"

continue

fi

bit_counter=10

oct_counter=0

user_bits=0

group_bits=0

other_bits=0

s_bits=0

set -A oct_array

oct_split=`print -- $perms|sed 's/\([-bcdDlprstwx]\)/\1 /g'`

for x in `print -- $oct_split`

do

oct_array[$oct_counter]=$x

let oct_counter=$oct_counter+1

done

while [ $bit_counter -gt 0 ]

do

case $bit_counter in

'9' ) if [ "${oct_array[$bit_counter]}" = "x" ]

then

let other_bits=$other_bits+1

elif [ "${oct_array[$bit_counter]}" = "t" ]

then

let s_bits=$s_bits+1

let other_bits=$other_bits+1

fi

let bit_counter=$bit_counter-1;;

'8' ) if [ "${oct_array[$bit_counter]}" = "w" ]

then

let other_bits=$other_bits+2

fi

let bit_counter=$bit_counter-1;;

'7' ) if [ "${oct_array[$bit_counter]}" = "r" ]

then

let other_bits=$other_bits+4

fi

let bit_counter=$bit_counter-1;;

'6' ) if [ "${oct_array[$bit_counter]}" = "x" ]

then

let group_bits=$group_bits+1

elif [ "${oct_array[$bit_counter]}" = "s" ]

then

let s_bits=$s_bits+2

let group_bits=$group_bits+1

fi

let bit_counter=$bit_counter-1;;

'5' ) if [ "${oct_array[$bit_counter]}" = "w" ]

then

let group_bits=$group_bits+2

fi

let bit_counter=$bit_counter-1;;

'4' ) if [ "${oct_array[$bit_counter]}" = "r" ]

then

let group_bits=$group_bits+4

fi

let bit_counter=$bit_counter-1;;

'3' ) if [ "${oct_array[$bit_counter]}" = "x" ]

then

let user_bits=$user_bits+1

elif [ "${oct_array[$bit_counter]}" = "s" ]

then

let s_bits=$s_bits+4

let user_bits=$user_bits+1

fi

let bit_counter=$bit_counter-1;;

'2' ) if [ "${oct_array[$bit_counter]}" = "w" ]

then

let user_bits=$user_bits+2

fi

let bit_counter=$bit_counter-1;;

'1' ) if [ "${oct_array[$bit_counter]}" = "r" ]

then

let user_bits=$user_bits+4

fi

let bit_counter=$bit_counter-1;;

0 ) let bit_counter=$bit_counter-1;;

* ) let bit_counter=$bit_counter-1;;

esac

done

octal=${s_bits}${user_bits}${group_bits}${other_bits}

print -- "$octal $filename"

done

#

# 2007 - Mike Golvach - eggi@comcast.net

#

# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#

arg=$@

ls -l $arg|awk '{ if ($0 !~ /^$/) print $1 " " $NF}'|grep -v "^total"|while read perms filename

do

if [ $filename = $perms ]

then

print "$filename = Directory"

continue

fi

bit_counter=10

oct_counter=0

user_bits=0

group_bits=0

other_bits=0

s_bits=0

set -A oct_array

oct_split=`print -- $perms|sed 's/\([-bcdDlprstwx]\)/\1 /g'`

for x in `print -- $oct_split`

do

oct_array[$oct_counter]=$x

let oct_counter=$oct_counter+1

done

while [ $bit_counter -gt 0 ]

do

case $bit_counter in

'9' ) if [ "${oct_array[$bit_counter]}" = "x" ]

then

let other_bits=$other_bits+1

elif [ "${oct_array[$bit_counter]}" = "t" ]

then

let s_bits=$s_bits+1

let other_bits=$other_bits+1

fi

let bit_counter=$bit_counter-1;;

'8' ) if [ "${oct_array[$bit_counter]}" = "w" ]

then

let other_bits=$other_bits+2

fi

let bit_counter=$bit_counter-1;;

'7' ) if [ "${oct_array[$bit_counter]}" = "r" ]

then

let other_bits=$other_bits+4

fi

let bit_counter=$bit_counter-1;;

'6' ) if [ "${oct_array[$bit_counter]}" = "x" ]

then

let group_bits=$group_bits+1

elif [ "${oct_array[$bit_counter]}" = "s" ]

then

let s_bits=$s_bits+2

let group_bits=$group_bits+1

fi

let bit_counter=$bit_counter-1;;

'5' ) if [ "${oct_array[$bit_counter]}" = "w" ]

then

let group_bits=$group_bits+2

fi

let bit_counter=$bit_counter-1;;

'4' ) if [ "${oct_array[$bit_counter]}" = "r" ]

then

let group_bits=$group_bits+4

fi

let bit_counter=$bit_counter-1;;

'3' ) if [ "${oct_array[$bit_counter]}" = "x" ]

then

let user_bits=$user_bits+1

elif [ "${oct_array[$bit_counter]}" = "s" ]

then

let s_bits=$s_bits+4

let user_bits=$user_bits+1

fi

let bit_counter=$bit_counter-1;;

'2' ) if [ "${oct_array[$bit_counter]}" = "w" ]

then

let user_bits=$user_bits+2

fi

let bit_counter=$bit_counter-1;;

'1' ) if [ "${oct_array[$bit_counter]}" = "r" ]

then

let user_bits=$user_bits+4

fi

let bit_counter=$bit_counter-1;;

0 ) let bit_counter=$bit_counter-1;;

* ) let bit_counter=$bit_counter-1;;

esac

done

octal=${s_bits}${user_bits}${group_bits}${other_bits}

print -- "$octal $filename"

done

, Mike

linux unix internet technology