Good afternoon, stackoverflow friends!
I have been given the following assignment and would like to learn how to see if a file or directory exists.
"Prompt the user to type in one parameter (note that this script only takes in one parameter and should report warnings/errors if the user input contains zero or multiple parameters), check if the input parameter is a filename or a directory name.
1) If the user input is a file, exit when the file is an empty file, and print the last line of the file.
2) If the user input is a directory, exit when the directory is empty, use a hash table to record the filenames inside this directory and the assess ages of these files (the number of days since the files were lastly assessed), find the oldest file (based on modification time) in the directory, and print the absolute path to this file."
I have spent the last 2 days looking a detailed explanation of how to use File::Find but cannot it. Below is my code and I'd like to replace -e $input sections with File::Find because with the -e file operator, I can only search in my current directory and not my entire system. I look forward to your replies and greatly appreciate your time.
#! /usr/bin/perl
# Assignment 9, check and read files and directories
use strict;
use warnings;
use Module1;
assnintro();
my @parameter;
my $input;
do { # This loop keeps calling pamcheck subroutine until the 1 param entered
# is a file in the directory, but I'd to expand the file test operator
# to all directories
$input = ();
@parameter = ();
pamcheck( \@parameter );
$input = $parameter[0];
if ( -e $input ) { } # Instead of simply checking current directory, I want to
# I want to see that the file exists in my system
else {
print color 'red';
print "The file or directory you entered, doesn't exist.\n";
print color 'reset';
}
} until ( -e $input );
if ( -d $input ) {
print "I am a directory.\n";
} else {
}
exit;
sub pamcheck { # This subroutine asks user to to enter a file or directory name
my ($parameter) = @_; # In the terminal, "parameters" are separated by space
my $elementcount; # Do elem ct. to make sure usr only entered 1 parameter
do {
@$parameter = ();
print "Enter one file or directory name: ";
@_ = split( /\s+/, <> ); # "Enter" key act as Ctrl D to avoid infinite
# param entry
push( @$parameter, @_ );
$elementcount = 0;
foreach (@_) {
$elementcount++;
}
if ( $elementcount != 1 ) { # Error msg if 1 param isn't entered
print color 'red';
print "Please enter only ONE parameter.\n";
print color 'reset';
} else {
}
} until ( $elementcount eq 1 ); # Loop continues until one param is entered
}
File::Finddoesn't do what you think it does. It's based on the Unixfindcommand which traverses a directory tree. (And may do stuff to all files in a directory tree).The reason you need this is it's harder than you might think to do a deep traversal of a filesystem, in a world with symbolic links, mountpoints etc. Hence a utility to do it.
What
File::Findwill let you do is specify a chunk of code to run on e.g. each file iffind.As an example -
That aside - there's several things in your code that seems to suggest you're going off in an odd direction.
counting elements in an array is much simpler by testing the array in a scalar context. Instead of:
for ( @array ) { $elementcount++; }
You can just do:
splitting
STDINon spaces is a bit risky, because it assumes you have no filename with spaces in. But lets stick with it for now.NEVER assign values to
@_. This is a built in variable, and messing with it can break things in strange and horrible ways.Why have you encapsulated the 'getting input' into a subroutine?
Anyway - assuming you need to traverse the filesystem to find your directory/files:
Hopefully that should get you started? What's happening is - you're using File::Find to give you a list of matches for a text string, that you can then go through and process individually. Bear in mind that your assignment spec is unclear on what you should do if you have a directory and a file that matches, which is why I'm not convinced you need to do the traversal.