Read-only files are only protecting the data from being changed, and that a file and a filename are different. file readable may examine file contents file writable may alter file contents file executable may run file contents directory readable may examine directory contents (list filenames in directory) directory writable may alter directory contents (remove or rename filenames) direcory executable may use directory as component in pathnames, or chdir to that directory Permissions are on files, not filenames. Control of filenames is left up to the directory. Directories contain filenames (not files!), that themselves refer to files. Look at this. Assume you are the owner of all files and directories listed, and that your umask (creation mask) is 022. directory filename file inode perms ---------- --------- ----------- ------ alpha . 100 0755 alpha foo 101 0644 alpha bar 102 0444 beta . 200 0555 beta foo 201 0644 beta bar 102 0444 Consider two directories, alpha and beta, each of which have the same two filenames, foo and bar. alpha/foo is really file #101, but beta/foo is really file #201 -- different files. However, the two bar filenames both refer to the same file, because both #102. It's just two links (filenames) to the same file. The unlink() (remove filename) call does not delete a file -- it deletes a filename. When you link() a file into a directory, or creat() a new file there, it is the directory's permissions that matter. Likewise, a rename() is not changing a file -- it's changing its name. Now, since the ability to modify something is controlled by the write-permission bit, and THE THING YOU ARE MODIFYING WHEN RENAME A FILE(NAME) IS A DIRECTORY, all you look at to rename or remove a filename is the permission of THE DIRECTORY, because it is the DIRECTORY that you are modifying, not the file. rename does not So what happens? Consider this perl -i.bak -pe 1 alpha/foo Perl wants to do this rename alpha/foo to alpha/foo.bak create a new alpha/foo Now, alpha/foo is permission 0644, which means you can write it, *BUT THIS IS IRRELEVANT*. You are not altering the file. You moved it out of the way and created a new one. Moving and creating are governed by the directory's permissions. Since alpha is mode 0755, this is allowed, now giving us the following: directory filename file inode perms ---------- --------- ----------- ------ alpha . 100 0755 alpha foo 101 0644 alpha foo.bak 301 0644 alpha bar 102 0444 beta . 200 0555 beta foo 201 0644 beta bar 102 0444 What happens when you try to do this? perl -i.bak -pe 1 alpha/bar Well, you seem to think you shouldn't be able to rename it because it's mode 0555, readonly. But that's irrelevant. It's the diretory that matters. So it succeeds. Afterwards, we have this setup: directory filename file inode perms ---------- --------- ----------- ------ alpha . 100 0755 alpha foo 101 0644 alpha foo.bak 301 0644 alpha bar 302 0644 alpha bar.bak 102 0444 beta . 200 0555 beta foo 201 0644 beta bar 102 0444 Notice that inode 102, alpha/bar.bak and beta/bar, have never been touched. We haven't modified the contents of the file. We can't. It's read only. What happens when you do this: perl -i.bak -pe 1 beta/foo The answer is that you get permission denied. Ah, you say, this is a bug: the file (inode 201) is mode 0644, so I should be able to write it. And you *CAN* write it. If you opened it for writing (clobber), or appending, or update (read/write, no clobber), you would have succeeded. But you didn't try to do that. You tried to do this: rename beta/foo to beta/foo.bak create a new beta/foo But you can't do that, because to rename a file, or to create or unlink a file in a dirctory, you must be able to modify the directory. But beta is itself mode 0555, so you don't have permissions to alter it. So you lose. Likewise, if you try perl -i.bak -pe 1 beta/bar You lose, but it is not because beta/bar (currently pointing to file number 102, which is the same file that is pointed to by filename alpha/bar.bak) is readonly. That fact is irrelevant to this case. You may not run that command because you cannot rename the file to beta/bar.bak, which is illegal due to the readonly *DIRECTORY*. On the other hand, beta/bar will also stop you from changing the file itself, because unlike beta/foo, which is mode 0644, beta/bar is mode 0444 and may not be altered. In short, going back to the original situation directory filename file inode perms ---------- --------- ----------- ------ alpha . 100 0755 alpha foo 101 0644 alpha bar 102 0444 beta . 200 0555 beta foo 201 0644 beta bar 102 0444 The file indicated by alpha/foo, inode #101, may be changed due to its permissions of 0644, and that filename may be renamed and unlinked due to its directory's permissions of 0755. The file indicated by alpha/bar, inode #102, may *NOT* be changed due to its permissions of 0444, but that filename may be renamed and unlinked due to its directory's permissions of 0755. The file indicated by beta/foo, inode #201, may be changed due to its permissions of 0644, but that filename may be *NOT* renamed or unlinked due to its directory's permissions of 0555. The file indicated by beta/bar, inode #102, may *NOT* be changed due to its permissions of 0444, and that filename may be neither renamed nor unlinked due to its directory's permissions of 0555.