MrFloydFreak42 has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks, I'm trying to write a script that will look for all the files ending in .bak in a directory, but I am having a problem.
#!usr/local/bin/perl -w use strict; my $count; my $in; my @files = glob '*.bak'; foreach my $file (@files) { $count++; } print "$count backup files found!\n\n"; print "Delete these files: (Y/N)? "; chomp ($in = <STDIN>); while ($in =~ /[^yn]/i) { print 'Y or N, please: '; chomp ($in = <STDIN>); } if ($in =~ /^y/i) { delfiles(); print "$count files were deleted!"; } sub delfiles { foreach my $file (@files) { open $file; unlink <$file>; } }

Whenever I try to run the program, strict complains about the symbolic references. Is there any way to bypass this on a Windows XP system? Thanks in advance.

Replies are listed 'Best First'.
Re: File Stricture Help
by pc88mxer (Vicar) on May 14, 2008 at 02:44 UTC
    Your basic problem is in the delfiles routine: the unlink function takes a path name (or a list of path names) not a file handle:
    sub delfiles { my $count = unlink @files; print "number of files deleted: $count\n"; }
    or you could just delete them one at a time using a loop:
    sub delfiles { for my $path (@files) { unlink $file; } }
    which allows you to do something special if the file can't be deleted.

    There are other issues with your script, but since this smells like a homework problem, it's probably best if you first attempt to figure those out on your own.

      Thanks alot, I didn't realize that.
Re: File Stricture Help
by chromatic (Archbishop) on May 14, 2008 at 02:51 UTC
    foreach my $file (@files) { $count++; }

    This is usually simpler as:

    my $count = @files;

    And this:

    unlink <$file>;

    ... reads from the filehandle $file (which isn't a filehandle, and is the source of your problems. The <> operator is the same as readline; it doesn't signify a file at all. I think that's what's confused you here.

      reads from the filehandle $file (which isn't a filehandle
      Yes and no. It's a string being passed to 1-arg open and readline, which are glob contexts. So it's interpreted as a symbolic glob reference (and a glob reference is the typical type of a filehandle), which makes strict complain.

      But without strict, it works just fine as a filehandle:

      $ perl -we'$file = "foo.bak"; ${"foo.bak"} = "seq 10|"; open $file or +die "nope:$!"; print for <$file>' 1 2 3 4 5 6 7 8 9 10

        I just didn't want to say "symbolic filehandle coercion".

Re: File Stricture Help
by chrism01 (Friar) on May 14, 2008 at 06:16 UTC
    Also, since you've declared all (top level/main) vars with 'my', which is a good thing, the var @files is not global, so it has nothing in it in the delfiles() sub...
      The  @files lexical variable is declared in file scope, and so will be "visible" within the subroutine and will have the expected content.

      That said, it would still be most preferable to pass the list of file paths-and-names to the subroutine as an argument list!