Sams Teach Yourself XML in 24 Hours, Complete Starter Kit, 3rd Edition. Part 1 | 4 | WebReference

Sams Teach Yourself XML in 24 Hours, Complete Starter Kit, 3rd Edition. Part 1 | 4

Files and Directories in Perl

Exercise: Renaming Files En Masse

This exercise will provide another (small) tool for your toolkit. This utility allows you to rename files given a directory name, a pattern to look for, and a pattern to change it to. For example, if a directory contains the filenames Chapter_01.rtf, Chapter_02.rtf, Chapter_04.rtf, and so on, you could rename all the files to Hour_01.rtf, Hour_02.rtf, Hour_04.rtf, and so on. This task normally isn't easy at a command prompt and just silly when you're using a GUI-based file browser.

Using your text editor, type the program from Listing 10.3 and save it as Renamer. If you can, be sure to make the program executable according to the instructions you learned in Hour 1.

When you're done, try running the program by typing the following at a command line:

perl -w Renamer

or, if you could make the program executable,


Listing 10.4 shows some sample output from this program.


This hour you learned how to create, remove, and rename directory entries by using the mkdir, rm, and rename functions in Perl. Also, you learned how to query the file system with stat to find out information about files, not just what's in them. During the course of this hour, the two exercises provided small but useful tools that you can use to make yourself more productive.


Q I'm having problems with the following program. No files are read in, even though they're in the directory!

opendir(DIRHANDLE, "/mydir") || die;
@files= ;

A Whoops! The problem is in the second line. DIRHANDLE is a directory handle, not a filehandle. You cannot read directory handles with the angle operators (). The correct way to read the directory is @files=readdir DIRHANDLE.

Q Why doesn't glob("*.*") match all the files in a directory?

A Because "*.*" matches only filenames with a dot in them. To match all the files in a directory, use glob("*"). The glob function's patterns are designed to be portable across many operating systems and thus do not behave the same as the *.* pattern in DOS.

Q I modified the mygrep exercise to search subdirectories by using opendir and some more loops, but it seems to have bugs.

A In short: Don't Do That. Descending a directory tree is an old problem, it's not particularly easy, it's been solved many times before, and you don't need to do it for yourself. (Doing all that work on a problem that's already been solved is called "reinventing the wheel.") If you're doing it only for fun, that's wonderful, but don't spend too much time on it. Hold on until Hour 15, where you'll learn to use the File::Find module instead. It's a lot simpler to use—and, more importantly, it's debugged.

Q The program in Listing 10.3 gives an error if I try to change *.bat to *.tmp. Why?

A The program wasn't expecting you to type *.bat as a pattern to look for. *.bat isn't valid to have in a regular expression—* must follow some other character. If you had entered \*\.bat, the program would have accepted the input just fine—although it might not have worked as expected because filenames hardly ever have a literal * in them.

To fix this error, either give the program the input it expects (simple strings) or change line 19 to read s/\Q$oldpat/$newpat/ so that "special characters" are disabled in the regular expression patterns.



1. To print the last modification time of the file foofile, use

2. The unlink function returns



Excerpted from Sams Teach Yourself Perl in 24 Hours, 3rd Edition by Clinton Pierce. ISBN 0672327937, Copyright © 2005. Used with the permission of Sams Publishing.


Created: March 27, 2003
Revised: February 3, 2006