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

This code
#!/usr/bin/perl -w use strict; use diagnostics; for (</home/www/*/logs/weekly>); my $a=$_; substr($a,-7)=" "; print $a;
results in this error message:
Can't use string ("/home/www/xyz/logs/weekly") as a symbol ref while " +strict refs" in use at lr15.pl line 16 (#1) (F) Only hard references are allowed by "strict refs". Symbolic references are disallowed. See perlref. Uncaught exception from user code: Can't use string ("/home/www/xyz/logs/weekly") as a symbol ref whi +le "strict refs" in use at lr15.pl line 16.

How can I get around this problem?

Replies are listed 'Best First'.
Re: Symbolic reference problem
by Cine (Friar) on Aug 20, 2001 at 14:47 UTC
    opendir (D,'/home/www/'); while (defined(my $subdir = readdir D)) { open F, '/home/www/'.$subdir.'/logs/weekly' || do {warn "Couldnt open home/www/$subdir/logs/weekly: $!"; next}; while (<F>) { #your code } }
    hope this helps
    Update:

    UPS... As pointed out below, I forgot to close my filehandles :(

    T I M T O W T D I
      You forgot to both close your filehandles and your dirhandle. Rewritten, this should look like:
      opendir LOG_DIR, '/home/www/' or die "Cannot opendir /home/www"; while (defined(my $subdir = readdir LOG_DIR)) { open IN_FILE, '/home/www/'.$subdir.'/logs/weekly' || do {warn "Couldnt open home/www/$subdir/logs/weekly: $!"; next}; while (<IN_FILE>) { #your code } close IN_FILE; } closedir LOG_DIR;
      Yes, I know that Perl will implicitly close stuff for you, and that's fine for one-offs. BUT ... if this is going to run more than once or possibly be looked at by someone else, do things explicitly! And, it doesn't matter that something is 0.01 CPU seconds slower. CPU is cheap! Human-time is much more expensive, usually by a factor of 10,000 or more.

      ------
      /me wants to be the brightest bulb in the chandelier!

      Vote paco for President!

Re: Symbolic reference problem
by mirod (Canon) on Aug 20, 2001 at 14:28 UTC

    for (</home/www/*/logs/weekly>);

    You are trying to read from a file name. You cannot do this in Perl. You have to read from a filehandle. To create a filehandle you need tp open the file:

    open( LOG, "</home/www/logs/weekly>") or die "cannot open the log: $!"; while( <LOG>) { ...

    Of course this will not work in your case as you are trying to read from several files using /home/www/*/logs/weekly. So the best way if for you to call the script using process /home/www/*/logs/weekly and to just read fron STDIN:

    while( <>) # reads from STDIN { ...
      • You are trying to read from a file name.
        No, I don't think so. This looks to me like the file globbing operator (same as glob). And this should work - once the syntax error after for is fixed. So rewriting a little bit:
        # added braces and changed variable name for my $filename (</home/www/*/logs/weekly>) { substr($filename,-7)=" "; print $filename; }

      • while(<>) # reads from STDIN
        and again no, this reads from the magic filehandle ARGV - which results in a read from STDIN when @ARGV is empty, otherwise it interprets the arguments in @ARGV as filenames and reads from them.
        while (<STDIN>) { # this reads from STDIN ... }
        and you are right that <> is the best solution if you are trying to read from multiple files

      -- Hofmator

        My goodness, you are right!

        I completely forgot about the file glob operator, which I rarely use, and I completely missed the goal of the code. I thought that the goal was to read from all the files, not just to get the file names.

        Apologies! Maybe I should go back to doing some XML stuff...