home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book HomeLearning Perl, 3rd EditionSearch this book

Chapter 13. Manipulating Files and Directories

Perl is commonly used to wrangle files and directories. Because Perl grew up in a Unix environment and still spends most of its time there, most of the description in this chapter may seem Unix-centric. But the nice thing is that to whatever degree possible, Perl works exactly the same way on non-Unix systems.

And now a word of warning -- some cultures consider the number "13" to be very unlucky. We deliberately placed this material as Chapter 13, "Manipulating Files and Directories" of this book, since we're about to do some pretty dangerous things if bugs creep into the code (like remove files without a chance of recovery), so be very careful when you're playing with the exercises.

13.1. Removing Files

Most of the time, we make files so that the data can stay around for a while. But when the data has outlived its life, it's time to make the file go away. At the Unix shell level, we'd type an rm command to remove a file or files:

$ rm slate bedrock lava

In Perl, we use the unlink operator:

unlink "slate", "bedrock", "lava";

This sends the three named files away to bit heaven, never to be seen again.

Now, since unlink takes a list, and the glob function (described in Chapter 12, "Directory Operations") returns a list, we can combine the two to delete many files at once:

unlink glob "*.o";

This is similar to rm *.o at the shell, except that we didn't have to fire off a separate rm process. So we can make those important files go away that much faster!

The return value from unlink tells us how many files have been successfully deleted. So, back to the first example, we can check its success:

my $successful = unlink "slate", "bedrock", "lava";
print "I deleted $successful file(s) just now\n";

Sure, if this number is 3, we know it removed all of the files, and if it's 0, then we removed none of them. But what if it's 1 or 2? Well, there's no clue which ones were removed. If you need to know, do them one at a time in a loop:

foreach my $file (qw(slate bedrock lava)) {
  unlink $file or warn "failed on $file: $!\n";
}

Here, each file being deleted one at a time means the return value will be 0 (failed) or 1 (succeeded), which happens to look like a nice Boolean value, controlling the execution of warn. Using or warn is similar to or die, except that it's not fatal, of course (as we said back in Chapter 11, "Filehandles and File Tests"). In this case, we put the newline on the end of the message to warn, because it's not a bug in our program that causes the message.

When a particular unlink fails, the $! variable is set to something related to the operating system error, which we've included in the message. This makes sense to use only when doing one filename at a time, because the next operating system failed request resets the variable. You can't remove a directory with unlink (just like you can't remove a directory with the simple rm invocation either). Look for the rmdir function coming up shortly for that.

Now, here's a little-known Unix fact. It turns out that you can have a file that you can't read, you can't write, you can't execute, maybe you don't even own the file -- that is, it's somebody else's file altogether -- but you can still delete the file. That's because the permission to unlink a file doesn't depend upon the permission bits on the file itself; it's the permission bits on the directory that contains the file that matter.

We mention this because it's normal for a beginning Perl programmer, in the course of trying out unlink, to make a file, to chmod it to 0 (so that it's not readable or writable), and then to see whether this makes unlink fail. But instead it vanishes without so much as a whimper.[282] If you really want to see a failed unlink, though, just try to remove /etc/passwd or a similar system file. Since that's a file controlled by the system administrator, you won't be able to remove it.[283]

[282]Some of these folks know that rm would generally ask before deleting such a file. But rm is a command, and unlink is a system call. System calls never ask permission, and they never say they're sorry.

[283]Of course, if you're silly enough to try this kind of thing when you are logged in as the system administrator, you deserve what you get.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.