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,
Renamer
Listing 10.4 shows some sample output from this program.
Lines 13Â15: The entries in the directory indicated by $dir
are read into
@files
.
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 19.
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Â
for example, $dir/$oldnameÂbecause @files
doesn't contain full
pathnames, which you need for the rename.
Summary
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&A
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=
closedir(DIRHANDLE);
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.
Workshop
Quiz
1. To print the last modification time of the file foofile
, use
a. print glob("foofile");
b. print (stat("foofile"))[9];
print scalar localtime (stat("foofile"))[9];
2. The unlink
function returns
a. The number of files actually deleted
b. True or false, depending on success
c. The number of file deletions that were attemptedAnswers
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.Activities
- As a programming exercise only, try to write a program that lists all the files
in a directory, in its subdirectories, and so on.
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
URL: https://webreference.com/programming/perl_24/1