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_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
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.
Lines 13Â15: The entries in the directory indicated by
$dir are read into
Lines 17Â19: Each file from
@files is assigned to
$_ and that name is saved in
$oldname. The original filename in
$_ is then changed to the new name on
Line 20: Before renaming the file, this line makes sure the target filename doesn't already exist. Otherwise, the program could rename a file into an existing nameÂdestroying the original data.
Lines 21Â25: The file is renamed, and warnings are printed if the rename fails.
Notice that the original directory name needs to be appended onto the filenamesÂ
$dir/$oldnameÂbecause @files doesn't contain full
pathnames, which you need for the rename.
This hour you learned how to create, remove, and rename directory entries by using
mkdir, rm, and
rename functions in Perl. Also, you learned how to query the file
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;
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
Q Why doesn't
glob("*.*") match all the files in a directory?
"*.*" matches only filenames with a dot in them. To match all the
files in a directory, use
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
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
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
print scalar localtime (stat("foofile"));
unlink function returns
a. The number of files actually deleted
b. True or false, depending on successc. The number of file deletions that were attempted
1. b or c. Choice b prints the time expressed as the number of seconds since 1970Ânot very useful. Choice c prints the time as a nicely formatted string.2. a. However, choice b is also somewhat true. If no files can be deleted, unlink returns 0, which is false.
- As a programming exercise only, try to write a program that lists all the files
in a directory, in its subdirectories, and so on.
Created: March 27, 2003
Revised: February 3, 2006