Here's one way to do it:
foreach my $file (@ARGV) {
my $attribs = &attributes($file);
print "'$file' $attribs.\n";
}
sub attributes {
# report the attributes of a given file
my $file = shift @_;
return "does not exist" unless -e $file;
my @attrib;
push @attrib, "readable" if -r $file;
push @attrib, "writable" if -w $file;
push @attrib, "executable" if -x $file;
return "exists" unless @attrib;
'is ' . join " and ", @attrib; # return value
}
In this one, it's convenient to use a subroutine. The main loop prints one line of attributes for each file, perhaps telling us that 'cereal-killer' is executable or that 'sasquatch' does not exist.
The subroutine tells us the attributes of the given filename. If the file doesn't exist, there's no need for the other tests, so we test for that first. If there's no file, we'll return early.
If the file does exist, we'll build a list of attributes. (Give yourself extra credit points if you used the special _ filehandle instead of $file on these tests to keep from calling the system separately for each new attribute.) It would be easy to add additional tests like the three we show here. But what happens if none of the attributes is true? Well, if we can't say anything else, at least we can say that the file exists, so we do. The unless clause uses the fact that @attrib will be true (in a Boolean context, which is a special case of a scalar context) if it has any elements.
If we have some attributes, we'll join them with "and" and put "is" in front, to make a description like is readable and writable. This isn't perfect however; if there are three attributes, it will say that the file is readable and writable and executable, which has too many ands, but we can get away with it. If you wanted to add more attributes to the ones this program checks for, you should probably fix it to say something like is readable, writable, executable, and nonempty. Do this if it matters to you.
If you didn't put any filenames on the command line, this produces no output. This makes sense because if you ask for information on zero files, you should get zero lines of output. But let's compare that to what the next program does in a similar case, in the discussion below.