in reply to chmod and oct

The short answer is that you're using chmod incorrectly in the short example. In fact, you're doing exactly what chmod's docs say you shouldn't do: using a string of octal digits. The short example should read chmod 0755, $file;, NOT chmod '0755', $file;. The first arg to chmod should be a number. I'm amazed that works at all.

The long answer is a little more complicated, and involves the abstraction of a number. Basicly, there are many different ways to write a number, all of which perl's parser reads and translates into an abstraction that we call a number: a bunch of bits somewhere on a chip in your system. Exactly what bits are set doesn't depend on how the number is written, only on it's value. 0x1ED, 0755, 493, 0b111101101 and even 4_9_3 are all the same thing to perl, an abstraction called a number, which has the value of 493, along with a bunch of housekeeping information. To whit, if we try to print out a slightly more literal interpretation of this abstraction then what you get with just a plain print, it'll look the same, regardless of how you happened to spell the number:

>perl -MDevel::Peek -e "$n=0755; Dump $n" SV = IV(0x1928478) at 0x19245ac REFCNT = 1 FLAGS = (IOK,pIOK) IV = 493

OTOH, if you put somthing in quotes, it isn't a number, it's a bunch of characters that happen to look like a number to any humans that might happen to be looking at it. Now, perl will try to do the right thing between the to -- perl is losely typed (or untyped, depending on who you ask). However, while "493"+1==494 and 0755+1==494, "0755"+1==756. Why? Because "0755" isn't interpreted as a number when it appears in your program, it's interpreted as a string. While perl allows you to specify literal numbers in your program in quite a number of different formats, it's a little more strict in what, and how, it'll consider a number when converting from a string to a number. Specificly, it allows leading '-'s, digits '0'-'9', and '.'. It assumes all strings being converted from numbers are decimal, written in standard English notation with no ','s or other formatting characters. (It also assumes that the decimal seperator is '.', not ',', as found in German and a fair number of other languages.)

This means that '0755'+0 is 755, not 493.

As to your confusion in the long form of the program, you seem to be confused about the snippet in the docs of chmod. I can't say I blame you, it's not clear what's going on. The masking with &0777 is all that you need. The reason is that the UNIX "mode" value encodes both the type of file (regular, dir, symlink, chardev, blockdev, FIFO...), and the permissions (read, write, execute, misc / user, group, other). If you're going to be calling chmod, you only want the permissions part, so you "mask" them, by doing a bitwise and, which will return 1 bits only where both the first AND the second argument have a 1 bit. &0777 will give you only the permissions, and not the mode, from the return of stat. The note about using printf's %04o format is to get the number into a nice user-readable (mildly readable, anyway) string of digits -- not a number anymore. The oct() function takes that string of digits, and turns it back into a number.

I hope my writing is coherent enough that this clears things up, instead of making them more murky.

Update: Fixed silly errors. Yeah, adding one doesn't give you back the same thing!


Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).