File I0


File I/0

At this point, you should be comfortable printing to standard output with print and reading from standard input with <STDIN>. You may be wondering how to work with input and output from other sources. To do this, you will need to know about filehandles.

Standard 1/0

STDIN is an example of a filehandle. When you use <STDIN> in a variable assignment, Perl knows to get the value from standard input. STDOUT is another filehandle. The print command uses STDOUT automatically, although if you wanted to you could use print STDOUT to explicitly print to standard output.

There’s a third default filehandle in Perl, STDERR, which points to standard error. To print to standard error, use

 print STDERR "Error: filename argument expected.\n" if (! defined @ARGV) ;

Using Filename Arguments

The NULL filehandle <> (also called the diamond operator) allows you to read in the contents of files listed on the command line. <> can be used just like <STDIN>. For example, you could implement the UNIX command cat in a script called cat.pl like this:

 #!/usr/bin/perl -w use strict; print "$_" while (<>);

This script will print the contents of any filenames that are given as arguments, just like cat. Also like cat, cat.pl will wait for standard input if there are no arguments.

Perl recognizes the-command-line argument as a reference to standard input. So you could enter the command line

 $ grep " " files | ./cat.pl header - footer

to print the file header, followed by all the output from grep, followed by footer.

The names of the arguments to your script are in the variable @ARGV. If you are a C programmer, note that the first element of @ARGV is the first command-line argument, not the name of the Perl script itself. You can use the special variable $0 to get the script name.

Using perl -p

The -p option causes perl to enclose your script in a while (<>) loop. It also prints $_ at the end of each iteration. So cat.pl could actually be written as the single line

 #!/usr/bin/perl -p

Better yet, it could be entered directly at the command line as

 $ perl -pe ''

The centering program from the earlier section “The $_ Variable” could be implemented with the -p switch as well. To center the words in the file quotations, use the command line

 $ perl -pe 'print " " x ((80 − length())/2)' quotations                                Speak the speech                                   I pray you                            as I pronounced it to you                             trippingly on the tongue

Opening Files

You also need to be able to open your own files. The command

 open MYFILE, "myinputfile";

will open myinputfile for reading and assign it the filehandle MYFILE (it’s common to pick names in all caps for filehandles). Now you can use MYFILE to get data from this file just as you would use STDIN. For example,

 $firstline = <MYFILE>;

In some cases, Perl may not be able to open myinputfile. For example, the file may not exist, or you may not have permission to read from it. The line

 open MYFILE, "myinputfile" or die "Error opening $myinputfile: $!";

is a safer way to try to open a file. It tells Perl that, if it can’t open the file, it should die, meaning stop the script. Before it exits, it will print the error message to standard error. The $! variable contains the system error caused by the open statement. Printing this may help determine what went wrong.

When you open a file, you can specify the type of access with the familiar UNIX operators <, >, and >>, as shown here:

 open READFILE,   "<  inputfile";           # Open inputfile for reading. open WRITEFILE,  ">  outputfile";          # Open outputfile for writing. open APPENDFILE, ">> appendfile";          # Open appendfile to append data.

To write to a file, use

 print MYFILE "$output\n";

Or, if you plan to write a lot of output to one file, use

 select MYFILE; print "$output\n";

The select makes MYFILE the default filehandle for print. When you’re done printing to that file, use select STDOUT to reset STDOUT as the default print destination.

When you’ve finished using a file, you can close it. For example,

 close MYFILE;

Opening Command Pipes

Perl also lets you open pipes to or from other commands. For example,

 open LSIN, "ls |";

will let you read the files in the current directory with <LSIN>. Alternatively,

 open LPOUT, "| lpr";

will let you send output to lpr.

You can run a command directly by enclosing it in backquotes. For example,

 my @files = 'ls';

would assign a list of files in the current directory to @files.

Working with Files

This script shows some of the other ways to work with files. The script takes a list of directories and makes backup copies of the directories and the files they contain.

Don’t be scared by the length of this script. It could actually be much shorter, but it was written to be as clear and understandable as possible, not as short as possible.

 #!/usr/bin/perl -w use strict; foreach my $olddir (@ARGV) {       # Check that each argument is a valid directory name.       if (! defined $olddir | ! -e $olddir){             die "Error: Enter directory to back up. \n";       }       # The backup directory will have .bk at the end.       # Check that it doesn't yet exist.       my $newdir="$olddir.bk"       if (-e $newdir) {              die "Error: Backup directory $newdir already exists.\n";       }       # Call the function that does all the work.       &backupdir ($olddir, $newdir); } sub backupdir {       my ($olddir, $newdir)=@_;       # Use the Perl mkdir command to create the new directory.       print "Creating backup directory $newdir ... ";       mkdir $newdir;       print "Done.\n";       # Iterate through all the files in the source directory.       foreach my $oldfile (glob "$olddir/*") {             # The new filename has .bk at the end.             my $newfile="$oldfile.bk";             # Change the path to include the new directory.             substr($newfile, 0, rindex ($newfile, "/")/ $newdir)             # Running the UNIX command cp to copy the file.             print "Copying $oldfile to $newfile ... ";             'cp $oldfile $newfile';             print "Done.\n";       } }

There are a few new commands in here. The test -e filename checks to see if a file exists. Other file tests, such as how to tell what type a file is, are listed in http://perldoc.perl.org/functions/-X.html. The glob command expands a filename that contains wildcards, such as *, into a list of matching files in the current directory.

The mkdir command is built in to Perl. It works just like the UNIX command with the same name. Perl does not have a built-in command to copy a file, however. In this script, we used backquotes to run the UNIX cp command. Of course, this will only work on a UNIX system. Once you know how to work with modules, you could use the Copy command from File::Copy instead, which will work on any system your Perl script runs on.

If the directory you are backing up contains other directories, the cp command won’t be able to copy them. You could use cp -r, but it still wouldn’t change the names of the files in those directories. In order to do that, you would need to use the procedure backupdir recursively If you know how to use recursion, this might be a good exercise.




UNIX. The Complete Reference
UNIX: The Complete Reference, Second Edition (Complete Reference Series)
ISBN: 0072263369
EAN: 2147483647
Year: 2006
Pages: 316

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net