95

Chapter 7:

Filing The Edges

You cannot create experience.
You must undergo it.

- Albert Camus, Notebooks 1935-1942, I. tr. Philip Tody

You can only go so far by interactively typing all of your data into a pro-
gram. Sooner or later, you'll have one or more files full of data you want to
work on. These files could come from many places: exported tabular data
from a spreadsheet program or a database application, calendar or contact
data from an organizer application, email archives, or even another Perl
program. In order to process this data, your Perl program will need to be
able to open, read from, and possibly write to, files on your disk.

Perl works with files by means of a data type called a filehandle. File-
handles are also used when working with devices(things like printers or
windows on the screen) and sockets.
1Sockets are discussed later in the book,
in relation to networking applications. The analogous data type for work-
ing with directories (folders), by the way, is the directory handle.
2

Filehandles

A filehandle is, simply, a symbolic name (a handle) that you attach to a
file so that you can refer to it and access it throughout your program. By

IMAGE imgs/212.Filing01.gif

1and pipes, on systems that support them
2Filehandles have a separate namespace from directory handles.


IMAGE imgs/212.Filing02.gif

associating a filehandle with the actual file on disk, Perl hides much of
the internal complexity of working with files from you, the programmer.

You choose the names for your filehandles, using the same naming rules as
for variables. That is, a filehandle name can consist of letters, numbers, or
underscores, and must begin with a letter or underscore.

To make things easier, Perl provides three predefined, standard filehan-
dles for working with input and output.
3These predefined filehandles are
initially associated with devices, not with files. We've already seen an
example of a filehandle in the previous chapter.
STDINis a predefined
filehandle that refers to standard input(usually typed at the keyboard).

There are two predefined filehandles for working with output. STDOUTis
the filehandle associated with standard output(normally the MacPerl
window).
STDERRis associated with standard error output; this is
normally set to the MacPerl window, but it can be separated so that error
messages from your program don't get mixed up with the regular output.
4

By now, you should have noticed some patterns in the names of these file-
handles. For one thing, each name is written entirely in uppercase letters
(remember that Perl is case sensitive).
5For another, each name begins with
STD, to indicate that it is a standard filehandle.

By convention, filehandles are named in all uppercase letters, to distin-
guish them from function names and other keywords. (Case is not necessary
to distinguish filehandles from variable names, as variable names always
begin with
$, @, or %.) You aren't required to use this naming convention
(TMTOWTDI, after all), but we recommend it strongly. Conventions such as
this one help make your programs easier to read and maintain.

IMAGE imgs/212.Filing01.gif

3The three pre-defined standard filehandles are pre-opened as well. Each can be re-
openedas needed to associate it with something else, such as a different window or a
file on your disk. We advise you not to closethe standard filehandles unless you
really understand what you are doing!
4The separation is done by re-opening either STDERRor STDOUT(or both) in associa-
tion with a file or a different device (e.g., a different window). We'll cover this in more
detail under Redirecting Standard I/O, later in this chapter.
5You may be interested to know that the filehandles stdout, stderr, and stdinare
also predefined and pre-opened as synonyms for the ones discussed here. We recom-
mend, however, that you stick with the uppercase versions.


IMAGE imgs/212.Filing04.gif

We also recommend that you choose names that are mnemonic(easy to
remember) and related in some way either to the file you are opening (e.g.,
LOG) or to how you are using that file (e.g., IN). As with variable names, a
filehandle name can be arbitrary (within the set of alphanumeric charac-
ters and _); however, as with variable names, your choice should be well-
considered. You may enjoy calling all of your filehandles
FREDand BART,
but the next person to read your program probably won't thank you for it!

You attach a filehandle to a file by using the openfunction, which takes
two arguments: the name of the filehandle you are creating and the name of
the file you wish to open. The file will be opened and the filehandle will
be associated with the file until you
closeit (or exit the program).

If you open a file using a filehandle that is already associated with anoth-
er file, the first file will be silently closed and the filehandle will be reas-
sociated with the new file! Be careful to keep track of your filehandles,
and use memorable names to avoid accidentally closing files you thought
were open (and thereby confusing your data).

Files may be opened for reading(the default), writing, or appending. You
can also open for reading and writing simultaneously.
6You tell Perl which
you want to do by inserting extra characters (e.g.,
>) before the filename.7

open(IN,'mydata'); # open mydata for reading
open(IN,'<mydata'); # explicit open for reading
open(IO,'+<mydata'); # open for read and write
open(IO,'+>mydata'); # open for read and write
open(OUT,'>newfile'); # create or truncate newfile
open(ADD, '>>oldfile'); # create or append to oldfile

If you open a file for writing, and the file already exists, the existing data
will be deleted upon opening. If you want to write to an existing file with-
out destroying its current contents, be sure to use the append mode. When you

IMAGE imgs/212.Filing01.gif

6Exercise caution if you do this; you could easily make a mistake! Use of temporary
files is generally safer.
7These characters, <, >, and >>, will be familiar to readers who have used a DOS- or
Unix-based operating system. If they are unfamiliar to you, think of them as arrows; <
"comes from" and >"goes to" the named file (>>adds to the end of the file).


IMAGE imgs/212.Filing06.gif

are finished using a file, you can close the filehandle (disassociating it
from the file) by using the
closefunction.8

close(IN);

Reading Input

Once you have opened a file and attached a filehandle to it, you can read
data from (or write data to) the file. You can use the filehandle anywhere
in your program that you need to work with the associated file.

This may seem a little strange at first (you may be asking "why can't I just
work with the file directly?"), but there are good reasons for using file-
handles. File I/O can get complicated and messy; filehandles hide most of
the details and make working with files much easier.

The following piece of code opens a file called READMEand attaches it to
the filehandle,
IN. It then loops over each line in the file, reading and
printing each line in turn. We use the line inputor angleoperator to read
the data from the filehandle; evaluating a filehandle within angle brac-
kets,
<>, yields each line of the associated file, in turn.9(Recall from the
previous chapter that we read lines from the keyboard using
<STDIN>.)

open(IN, 'README');
while ($line = <IN>) {
print($line);
}
close(IN);

If you enter this code into a new MacPerl script and run the script without
saving first, the script will attempt to open the file
READMEin the MacPerl
ƒ
folder. However, if you save the script and then run it, it will try to open
a file called
READMEin the same folder where you saved the script.

Note:Unix and MPW have a concept called the current directorywhich
refers to the directory where things will happen by default. For most
Macintosh applications, the current directory is less well defined. It
may be the folder where the application resides or the folder where

IMAGE imgs/212.Filing01.gif

8It's good practice to close your filehandles, but don't worry if you forget. Perl closes
all open filehandles when a program finishes and exits.
9TMTOWTDI: print while <IN>;


IMAGE imgs/212.Filing08.gif

the currently open document (file) can be found. Alternatively, the "cur-
rent" folder may be the most recent folder visited by the application, or
it may be the
Documentsfolder.

If you tried saving the script as we just mentioned, you may have noticed
some peculiar results (depending on where you saved the script). If there is
no file called
READMEin the same folder as the saved script, nothing is
printed
. Perl doesn't complain that it can't find the file
README.

If you try to open a file that doesn't exist (or which cannot be opened for
some other reason), the
openfunction will return an error. However, unless
you capture the error and act upon it, Perl will go happily on processing
your script (and the results will probably not be what you planned!).

Error Handling

To avoid confusion, most Perl programmers check the statusof the open,
printing an appropriate error message if something went wrong.
10Perl pro-
vides several functions to make error handlingeasier. If the problem is
serious (e.g., the input file cannot be opened) there is probably very little
point to continuing. In this case, you should use
die, which causes your
program to stop immediately.

open(IN, 'README') or die;

This statement can be read as "open READMEor die". If the file (README)
cannot be opened, the program will stop, printing
Diedto the screen.

This is an improvement over what we had before; at least the program
doesn't keep trying to go on without input. But
Diedis not a particularly
informative error, especially if there was more than one location in your
program where something could have gone wrong.

open(IN, 'README') or die('Could not open README');

If you supply diewith a message string, it will print that string to STDERR
before exiting.11We recommend including the name of the file that couldn't

IMAGE imgs/212.Filing01.gif

10Many Perl functions return status (1 for success; 0 for failure). In general, it's a very
good idea to check the status of these function calls and handle any errors. If you don't,
and the function fails, the results may be very mysterious indeed.
11In fact, dietakes a listas its argument and will print the concatenated value of that
list. In many cases, however, this means that it will print the string you told it to print.


IMAGE imgs/212.Filing10.gif

be opened, as well as any other pertinent information, in the message. If the
message string does not end with a newline, Perl will append the name of
the current script and the current line number to the message.

# Could not open file.
File 'HD:scripts:foo.pl'; Line 1

This may or may not be useful (line numbers can be very helpful for debug-
ging purposes, but they may only confuse a future user of your program).

If the situation is not so serious that you want the execution of your program
to cease, use
warninstead. Like die, warnprints a message on STDERR, but
it won't cause the program to stop.

warn("Warning: Debugging is on!\n") if ($DEBUG != 0);

Again, if you leave out the newline,\n, warnwill include the name of the
script and the current line number in its message.

Pathnames

So far, we've covered opening a file which can be found in the "current
directory" (probably the same folder where you've saved your Perl script).
This isn't very flexible, however. It shouldn't be necessary to store all of
your data files in the same folder as your programs! How do you open a file
that is located somewhere else on your disk (or even on another volume)?

There are several ways to open an arbitrary file. You can:

  • specify the file within your Perl script, using its pathname
  • put up a dialog, allowing users to navigate to and choose a file
  • create a MacPerl droplet, then drag and drop the file onto it

We'll get back to the latter two methods (dialog boxes and droplets ) in the
next chapter. For now, let's continue our discussion of pathnames.

A filename (e.g., README) is the name of a file found within a particular
directory. The name need not be unique; another directory may contain a file
with the same name. Thus, to allow unambiguous references to a specific
file, we must specify the pathto that file through the filesystem.

A full pathnamebegins with the name of the volume, followed by the
names of all folders which need to be opened until you reach the folder


IMAGE imgs/212.Filing11.gif

containing the file of interest. Each part of the pathname is separated from
the other parts by a colon,
:.12The output message from diein the example
in the previous section contained a full pathname to the script that died.

File 'HD:scripts:foo.pl'; Line 1

In this case, HDis the name of a volume (a disk); scriptsis a folder at the
top level of that volume;
foo.plis a file in the scriptsfolder.

A relative pathnameis similar to a full pathname, but contains the path
from the current directory to the desired file or folder; that is, the folders
are named "relative" to the current directory. For example, the following
openstatement uses a relative pathname.

open(IN, ":stuff:README");

In this example, the folder stuffis presumed to be in the current directory.
The file,
README, is expected to be in the stufffolder.

On the Macintosh, full pathnames always begin with the name of a disk
volume.
13Elements are separated by colons, :. If the pathname contains
only a volume name, it must still contain (end with) a colon. If any elements
contain spaces or tabs (let alone at signs or dollar signs!), be sure to quote the
entire pathname. (Hint: play it safe and use quotes for all pathnames...)

MyHardDisk:
'MyHardDisk:Desktop Folder:LaserJet 4'
'MyHardDisk:System Folder:Extensions:'
Perl:MacPerl:Mac_Perl_519r4_appl
HD:chapter6.pl

# volume
# file
# folder
# file
# file

Files that appear on the desktop actually reside in an invisible folder
named
Desktop Folderon the particular disk volume. Note that, although
all desktop files appear to be on the same "virtual" desktop, each disk vol-
ume actually maintains its own
Desktop Folder.14

IMAGE imgs/212.Filing01.gif

12Different operating systems use different separators. For example, Unix uses slashes,
/. MS-DOS uses backslashes, \.
13For example, a hard disk, CD-ROM, removable media, etc.
14And its own Trashas well.


IMAGE imgs/212.Filing13.gif

Note:You may have noticed what appear to be pathnames in Get Info
windows. Get Infowill show where a file resides, but its information
may be incomplete.

Keep in mind that Get Infodoes not show the full pathname of the file
itself, only of the folder or volume that contains it. Also,
Get Infoshows
the location of files on the desktop as if they were located in the rootof
the volume, rather than in the
Desktop Folder.

Relative pathnames begin with a colon, :(that is, they look a lot like full
pathnames, except they do not begin with a volume name). The double colon
construct,
::, means "up one level" in the folder hierarchy.15,16

:stuff:README
::
::CPAN:authors:

# file
# folder
# folder

The following code example illustrates full and relative pathnames, using
a function,
chdir, which changes the current directory to a named directo-
ry, and a command,
`pwd`, whichprints the full pathname to the current
working directory. If you try this example in MacPerl, be sure that the
MacPerl disc is loaded.

chdir('Perl:MacPerl') or warn;
print(`pwd`);
chdir('::') or warn;
print(`pwd`);
chdir(':CPAN:authors:Chris_Nandor') or warn;
print(`pwd`);

Note:Generally, expressions in backquotes, `, do not work in MacPerl
(unless you are running MPW Perl and have
ToolServerinstalled). The
backquote is used to evaluate a command "outside" of the Perl program
(e.g., a Unix shell command), which Mac OS does not allow. However,
several expressions, such as
`pwd`, are so popular that they have been
specially implemented (emulated, really) in MacPerl.

IMAGE imgs/212.Filing01.gif

15Readers familiar with Unix will recognize this as analogous to the ..construct in
Unix pathnames. Note, however, that :::is analogous to ../..(up two levels), etc.
16Do not confuse the ::in pathnames with the ::construct used by Perl modules!
They only look the same; the context is entirely different.


IMAGE imgs/212.Filing15.gif

Note that the returned value includes a newline, so you do not need to use \n
in the printstatement.17Also, note that the last printstatement may not
display what you expected. This statement prints

Perl:CPAN:authors:id:CNANDOR

because the folder named by the (relative) path

:CPAN:authors:Chris_Nandor

is actually an aliasto the folder

Perl:CPAN:authors:id:CNANDOR

When you access (e.g., openor chdirto) an alias from within a MacPerl
script, the result is the same as if you had accessed the file (or folder) that
the alias references.

We've included a small MacPerl droplet, path2clip, on the MacPerl disc, to
help you in using pathnames.
18When you drag and drop any file or folder
onto
path2clip,its full pathname is determined and copied to the Clip-
board. You can then cut and paste the path string into any text document,
such as a MacPerl script you may be writing.

Writing Output

We've been using printa lot, so you may feel fairly comfortable about
writing output. However, at this point we've only sent output to the Mac-
Perl window (also known as standard output or
STDOUT). So, let's consider
doing something more interesting, such as:

  • separating error messages from other output19
  • printing status messages to a log file
IMAGE imgs/212.Filing01.gif

17Do not enclose expressions such as `pwd`in double quotes; you will only get the
literal string `pwd`(backquoted expressions do not evaluate within double quotes).
18You can examine the code for path2clipby opening it from MacPerl (droplets cannot
be edited using a text editor such as BBEdit). We've used the Dartmouth XCMDs
package, discussed in more detail in Chapter 12, The MacPerl Package.
19Using Unix or MPW, you can redirectthe standard error and standard output to
(separate) files. The standalone MacPerl application has no provision for separating
standard error from standard output, but you should know it can be done in case you
port your script to another system (or MacPerl adds this feature in the future).


IMAGE imgs/212.Filing17.gif
  • sending different "streams" of output to different files based on
    characteristics of the data
  • printing output with a specific format

The first three of these alternatives can be accomplished using filehandles.
The fourth, printing output with a specific format, makes use of special for-
matting functions. We'll cover filehandles first and come back to formatted
printing shortly.

Recall that earlier we introduced STDOUT, a filehandle associated with
standard output (normally the
MacPerlwindow). In fact, STDOUTis the
default filehandle for output (just as
STDINis the default filehandle for
input). We could have specified the filehandle in the
printstatements in
any of our previous examples:

print STDOUT ($line);
print STDOUT (`pwd`);

You may have noticed something a little unusual about these statements.
Isn't
STDOUTan argument to print? Did we forget to include a comma?
(There's a comma after the filehandle when you use
open.) And why didn't
we put the filehandle inside the parentheses, as we did with
open?
What's going on?

The comma is specifically omitted after the name of the filehandle because
of the way the print statement works. The syntax of a print statement is

printFILEHANDLE list of things to print

So far, our lists of things to print have been confined to single strings. But
printcan just as easily include more than one thing (variables, strings,
expressions, etc.) in its list. (The use of multiple arguments to
printis
especially useful if one of the arguments is an expression to be evaluated.)

$name = 'Vicki';
print('My name is ', $name, ".\n");
print('Pi is approximated by ', 355/113, ".\n");

If you forget and follow the filehandle with a comma, Perl won't know
whether the first argument to
printis a filehandle or something to print!
This gets worse if you've stored a filehandle in a variable:

$loghndl = 'LOG';
open($loghndl, '>logfile') or die;


IMAGE imgs/212.Filing18.gif

print($loghndl, "Finished.\n");
print $loghndl ("Finished.\n");

# wrong!
# right

In fact, the need to write statements like this, where a filehandle is stored
in a scalar variable, is exactly the reason why the filehandle is not fol-
lowed by a comma.

Now you may have guessed why, in the previous examples, we put the
filehandle outside of the parentheses. The reason is to make it even more
clear that the filehandle is separate from the argument list (and to remind
ourselves not to include the comma).

print $loghndl ("Finished.\n");

Printing large blocks of text

If you need to print more than one or two lines of output in sequence, consider
using a here document
20rather than multiple print statements in a row. A
here document provides a special way of quoting a large block of text.
21It
begins by specifying a terminating string(preceded by the characters,
<<,
to indicate that this is a here document).

print <<EOF;

The start of the here document, and the specification of the terminating
string, are part of a statement, in this case a
printstatement. Be sure to
end this statement with a semicolon,
;, as usual. Lines of text to be printed
follow, until the terminating string appears by itself on a line.

The terminating string must be the only thing on the line; that is, it must not
be quoted or indented, and no other character may follow it except for a
newline
. Note that the terminating string must be followed by a newline
(i.e., be sure to type
RETURNafter EOF).

print <<EOF;
Mary had a little lamb,
its fleece was white as snow.

IMAGE imgs/212.Filing01.gif

20The term comes from Unix shell scripts, which can take input from a file (document)
as well as from the command line. When that input is specially encapsulated as part of
the script, the "document data" is said to be "right here", thus, the feature was referred
to as a "here document". Perl continues to use the name for historical reasons.
21Here documents canbe used for more than just printing output (e.g., to set a variable
to a multi-line string). The syntax is similar.


IMAGE imgs/212.Filing20.gif

And everywhere that Mary went
the lamb was sure to go.
EOF

If the specification of the terminating string is enclosed in quote marks, the
following lines of text will be processed as if they were quoted in the same
way. By default, lines of text are processed as if they were contained in
double quotes (i.e., variables and escape characters are interpolated). To
protect at signs, dollar signs, or quote marks within the text, use single
quotes in the specification.

print <<'EOF';
Mary spent $2.95 for soap to wash her
lamb's fleece and keep it snowy white.
EOF

Formatted output

Now suppose you want to exercise more control over what you print. For
example, if you tried out this example in MacPerl

print('Pi is approximated by ', 355/113, ".\n");

you would have seen this output

Pi is approximated by 3.14159292035398.

That's a little long. What if we would be satisfied to print only the first six
decimal places (with rounding)? We can do this with the formatted print
function,
printf.22

The syntax of printfis much the same as that of printexcept that a
format specificationprecedes the list of items to be printed. A format
specification consists of a string of (optional) text and field specifiers. The
remaining elements of the argument list are each substituted into the
format string, one per field specifier.
23

IMAGE imgs/212.Filing01.gif

22The formatand writefunctions provide yet another way to create formatted
output and reports. See Programming Perlfor information on these functions.
23Unlike C, if the number of field specifiers exceeds the number of elements in the argu-
ment list, Perl uses nulls to "fill in"; like C, it silently ignores any extra list elements.


IMAGE imgs/212.Filing22.gif

There are more than a dozen field specifiers, each of the form %x, where x
is a single character representing the type of field. The following are some
of the most common field specifier types.

%sa string
%ca single character
%dan integer (decimal number)
%fa floating point number
%ean exponential format floating point number

Many of these field specifiers can be modified by including the minimum
and/or maximum size of the field. The field specifier is then of the form
%m.nxwhere m is the minimum size and nis the maximum.24Padding (if
necessary) is done with spaces (and occasionally zeroes, for numbers).

Some examples should make things clearer; try these out!

$name = 'Vicki'; $pi = 355/113;
printf("My name is %s.\n", $name);
printf("My name is %16s.\n", $name);
printf("Decimal %d represents %c.\n", 42, 42);
printf("Decimal %d rings the bell %c.\n", 7, 7);
printf("Pi is approximated by %2.6f.\n", $pi);
printf("Pi is approximated by %d.\n", $pi);
printf("A millenium is %d years.\n",1000);
printf("A millenium is %8d years.\n",1000);
printf("A millenium is %08d years.\n",1000);
printf("A millenium is %1.2e years.\n", 1000);

Redirecting Standard I/O

Unless you do something to separate them, standard output and standard
error will both be sent to the same place (by default, the
MacPerlwindow).
However, if they both show up in the same place, what is the good of hav-
ing different filehandles for printing the messages?

Environments such as MPW (or Unix) allow you to redirectstandard I/O
from the command line, when you run a command. For example, you can
redirect
STDINto come from a file, rather than from keyboard input. Or,
you might specify that the standard output and standard error be separat-

IMAGE imgs/212.Filing01.gif

24For exponential formats, nrepresents the desired precision. A negative value for
minimum length will cause the field to be left-justified.


IMAGE imgs/212.Filing24.gif

ed, sending standard output to a file, but sending error messages to the
screen. However, the Finder does not have a command line; can you redirect
input and output from the standalone MacPerl application?

You can, because you can also redirect standard I/O from withina Perl
script. This is the method you must use when working with the standalone
MacPerl application. This form of redirection is accomplished by reopening
the appropriate filehandle and associating it with a new device (or with a
file on your disk).

For example, the following code forces STDINto be read directly from a file
rather than the keyboard.

open(STDIN, '<Datafile');

Recall that we said filehandles are also used for working with devices
(such as windows or printers). The following line of code will cause stand-
ard error to be printed to a separate window within MacPerl.

open(STDERR, '>Dev:Console:Messages');

The special pathname, Dev:Console:, doesn't actually refer to a location
on your disk, but rather to a window in the MacPerl application. The last
part of the pathname,
Messages, provides the title for this particular
window. Feel free to name the window with a name of your own choosing.

You can also print directly to a printer. This code reassociates STDOUTwith
your default (chosen) laser printer.
25

open(STDOUT, '>Dev:Printer');

As before, the filehandle is being associated with a device (in this case, a
printer), rather than with a file on your disk.
26For example, you might use
this technique to send PostScript code directly to the printer. The following
code prints an isosceles triangle.
27

IMAGE imgs/212.Filing01.gif

25Dev:Printeropens a PAP connection to your default laser printer. It is not guaran-
teed to work with any other type of printer (e.g., inkjet style printers).
26A third device, the nulldevice, is named by the pathname Dev:Null. Sending output
to the null device makes it disappear. This can be useful for temporarily suspending the
printing of error messages or even output, in some cases. Reading from the null device
guarantees an immediate end of file(EOF).
27Example from PostScript by Example, McGilton and Campione.


IMAGE imgs/212.Filing26.gif

open(STDOUT, '>Dev:Printer');
print STDOUT <<'EOF';
%!PS
72 144 moveto
306 648 lineto
540 144 lineto
closepath stroke showpage
EOF

Working With Folders (Directories)

Now let's suppose that you want to open, and work with, many files. If
those files are all in the same folder (directory), this is easy. All you have
to do is open the folder, get the list of files found inside, and then work
through the files one by one.

Working with directories in Perl is very similar to working with files.
First, you open the directory with the
opendirfunction, associating a
dirhandlewith the directory. Then, you read data (in this case, a list of
filenames) from the directory by means of the dirhandle. Finally, you close
the directory using the
closedirfunction, retaining the list of filenames
to process. The following code illustrates these steps.

opendir(DIR, ':') or die 'cannot open :';
@files = readdir(DIR);
closedir(DIR);
foreach $file (@files) {
print("$file\n");
}

The second argument to the opendirfunction is the pathname of the direc-
tory to open. In this case we are opening the current directory. (Just as
::
was a shorthand representation for the pathname of "the folder above this
one", a single colon,
:, is a shorthand representation for "the current direc-
tory".)

The readdirfunction reads the contents of the directory asociated with a
dirhandle and returns an array containing the names of all files, folders,
etc., that were found in that directory. Note that the names of allfiles and
folders are returned, including any that are invisible under the Finder!
28

IMAGE imgs/212.Filing01.gif

28You might be surprised at the number of invisible files stored on your disks!


IMAGE imgs/212.Filing28.gif

Once you have this array, you can close the dirhandle (you won't need it
again). Then you can process the files that were found, in whatever manner
you choose. For example, you might open each one in turn and examine its
contents, check or set file attributes such as Type and Creator, or perform
whatever other processing suits your needs.

Alternatively, you can use file globbing (wild card expansion), as described
in Chapter 8, Curious Constructions.

mkdir()

Unlike open(), the opendir()function does not create a directory if it
does not already exist. If you need to create a directory (i.e., make a new
folder), use the
mkdir()function.

mkdir('HD:new folder', 0755);

The second argument to mkdir()is the mode. Under Unix, the mode pro-
vides the directory permissions, that is, who can see files or make changes.
Directory permissions are unsupported in MacPerl. If you don't plan to port
your script to Unix, just pick a reasonable value (e.g.,
0755).29

If you aren't sure whether the directory already exists, you can use the -d
file test operator.30

if (! -d 'HD:new folder') {
mkdir('HD:new folder', 0755);
}

Working With Aliases

The Unix analog to the Mac aliasis the symbolic link.31Perl has several
built-in functions for working with symbolic links; to create an alias, use
the
symlink()function. The first argument to symlink()should be the
name of an existing file or folder. The second argument should be the name
of the alias to create.

symlink('HD:Trash', 'HD:Trash alias');

To test whether a file is an alias, use the -lfile test operator.z

IMAGE imgs/212.Filing01.gif

29Then, if you ever doport your script, the permissions will prbably be all right..
30There are many file test operators; see Chapter 19, Operators, for details
31Use caution. As with any analogy, this one is not quite perfect. But it's close

Copyright © 1997-1998 by Prime Time Freeware. All Rights Reserved.