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

I am once again having a devil of a time. This time standard error is not working for me as it should!

In my code below, I want to run a command that test an image file. If the identify command creates an error, it should write the file name to error.txt. All other info should go to dump.txt.

dump.txt works well and captures all but the error info. However, error.txt captures all file names.

. . . RetrieveValues(); CheckImageArchieve(); sub RetrieveValues { print "\n\nSpecify the Directory path to image folder:\n"; $directory = (<STDIN>); chomp $directory; # $directory =~ s/\\/\\\\/g; } sub CheckImageArchieve { my $a = 0; opendir(DIR, $directory) or die "Cannot open directory $directory" +; my @DIR = grep {$_ ne '.' && $_ ne '..' && grep (m/fpx/, $_)} read +dir DIR; system ("cls"); while ($DIR[$a]) { print "$directory\\$DIR[$a]\n"; system("echo $directory\\$DIR[$a] >> c:\\dump.txt"); system("identify -verbose $directory\\$DIR[$a] >> c:\\dump.txt"); or system("echo ERROR: $directory\\$DIR[$a] >> c:\\error.txt") +; $a=$a+1; } }

In the past, when I have had trouble with opening files, I would use the same redirection and it would work. I difficulty arises here because i am using a command line utility. Is my code proper, or is the command causing the issue?

Please advise,
Simon

Replies are listed 'Best First'.
Re: Redirecting errors
by PrimeLord (Pilgrim) on May 09, 2002 at 20:51 UTC
    Why are you using system calls to echo information into the files you want? It would be easier to do something like this.
    open STDERR, ">> error.txt" or die "$!"; system("identify -verbose $directory\\$DIR[$a] >> c:\\dump.txt") or print STDERR "Error: Error message here";

      Thanks, I it is always the simple things that are forgotten. I have a follow up though. When I run my script, even when the system command writes to the dump.txt and does not error, the script writes to the STDERR. I did not think this was possible with 'or'

      At this point I believe I have an issue with the command line application. Can an application be in a state where it is both in error and not in error--> my logic tells me this cannot be true. Or tells me this cannot be true--just wondering if there is something about STDERR I am not aware of... after all, I have only been writing perl for a year

      Thanks again,
      sdyates
        It is doing this because your system command is returning 0 (good in Windows but translated as false by Perl) if the command is sucessful and you are not capturing this value. if you do $garbage = system(blah) or "handle error" ; this will return true and things will work like you expect.

        The problem with that is that you will need to evaluate $garbage for a 0 value or die. So:
        $garbage = system("identify -verbose $directory\\$DIR[$a] >> c:\\dump. +txt"); if ($garbage != 0){ system("echo ERROR: $directory\\$DIR[$a] >> c:\\er +ror.txt") ;}
        Also grep's solution is a much better way to go for logging. Cleaner, quicker and not reliant on system() commands.

        "Nothing is sure but death and taxes" I say combine the two and its death to all taxes!
Re: Redirecting errors
by grep (Monsignor) on May 09, 2002 at 20:52 UTC

    This looks more like you really want logfiles rather than redirecting STDERR

    This is untested, but should work, if not it will give you a foundation on what to work with.

    The ` backtick operator is explained in perlop

    open(DUMP,">>./dump.txt") or die "could not open: $!\n"; open(ERR,">>./error.txt") or die "could not open: $!\n"; while ($DIR[$a]) { print "$directory\\$DIR[$a]\n"; print DUMP "$directory\\$DIR[$a]"; my $output = `identify -verbose $directory\\$DIR[$a]`; or print ERR "$directory\\$DIR[$a]\n"; print DUMP "$output\n"; $a=$a+1; }

    You should take a look at you indenting style. You current style makes it difficult to follow your logic



    grep
    Unix - where you can throw the manual on the keyboard and get a command
Re: Redirecting errors
by graff (Chancellor) on May 09, 2002 at 21:15 UTC
    Your posting showed 'system(...); or system(...);' which must be a typo -- perl would call "; or" a syntax error.

    Assuming you meant 'system("id...") or system("echo...");' then the problem may be a misunderstanding of what a shell process should normally return: zero if command was successful, non-zero otherwise. Maybe you want to try 'and' rather than 'or' between the 'system()' calls; if the first system calls returns with zero (meaning success), the second will not be executed.

    You may also want to simplify your syntax a bit, and use one less system call per iteration (since these tend to slow things down):

    open( ERRLOG, ">>c:\\error.txt" ); foreach (@DIR) { print "$directory\\$_\n"; system("echo $directory\\$DIR[$a] >> c:\\dump.txt"); system("identify -verbose $directory\\$_ >> c:\\dump.txt") and print ERRLOG "ERROR: $directory\\$_\n"; }
Re: Redirecting errors
by cmilfo (Hermit) on May 10, 2002 at 05:50 UTC
    I've seen a lot of luck using Log::Agent (here or here) in such situations. Of course, it looks like you are on a Microsoft OS (c:\) from your above snippet. I've never run Log::Agent on Win32. Has anyone else had any luck?

    Cheers!
    Casey