Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

foreach a writing open fails through not found file

by DomX (Initiate)
on Jun 23, 2019 at 12:59 UTC ( #11101758=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks!

This is the first time I write something here. Mostly I found solutions in documentations, existing entries here or platforms like stackoverflow.

This time I wasn't able to find a similar problem anywhere, so I decided to ask myself.
(There may be already the question answered anywhere I have, but I didn't get it, it was the same problem.)

foreach my $file ( @files ) { open(my $fh, ">>", $file->{full_path}); # or return(0); print $fh $file->{content}; close($fh); # or return(0); chmod(0755, $file->{full_path}); print "Created \"$file->{full_path}\" with $file->{line_counte +r} line" , ( $file->{line_counter} > 1 ) ? "s" : "" , "\n"; }
When this part of code is executed it tells me
print() on closed filehandle $fh at ./Make.pl line 223. Can't open perl script "../Path/to/file.pm": File or directory not fou +nd

First I didn't get it, because the returns just omitted writing the next files.
How can I do multiple open within the foreach, without print() failing?

I feel as if the open() wasn't executed every time as I expected
The loop is executed within a subroutine.

Replies are listed 'Best First'.
Re: foreach a writing open fails through not found file
by haukex (Chancellor) on Jun 23, 2019 at 13:05 UTC

    Hello and welcome to the Monastery, DomX!

    Note you aren't checking the open for errors; you've commented out the or return(0). So most likely, there's an error when opening the file that you're not seeing, which results in the "print() on closed filehandle" warning. Just yesterday, I posted several variants of non-fatal open error handling, here's one more I'll add to that post, for use in loops like these:

    FILE: for my $file (@files) { open my $fh, ... or do { warn "skipping $file: $!"; next FILE }; ... close $fh; }

      Hello haukex,

      I think this is a misunderstanding. The return(0) are the usual code. I just commented them out while debugging to find out, on which point the open() fails. The gathered information showed me that the print behaves, like it was called after the close($fh). This behavior is, what I don't understand.

      Your third example of your post you mentioned in "I posted", looks the very same to me like my foreach but reading. I think this works, but why does it stop to work, when I make it writing instead of reading and return()ing instead of die()ing?

        The return(0) are the usual code. I just commented them out while debugging to find out, on which point the open() fails. The gathered information showed me that the print behaves, like it was called after the close($fh). This behavior is, what I don't understand.

        Even during testing, you should still check open for success, and in the case of failure, output $! to see the error. Instead of commenting out the or return(0);, replace it with or do { warn $file->{full_path}.": $!"; return 0 };

        Again, in the code as you showed it above, if the open fails, then the code will continue on to the print $fh $file->{content};, which will cause the print() on closed filehandle $fh warning, and then the code should continue executing (the close, then the second print, and so on). Based on the information I see at the moment, the open is the most likely problem.

        I'm sorry, but I don't know what you mean by "the print behaves like it was called after the close($fh)", because I don't know how you would have determined this. It's also unclear to me where the "Can't open perl script "../Path/to/file.pm": File or directory not found" message is coming from. This is why a Short, Self-Contained, Correct Example is important: could you edit down your code to the minimum required to reproduce the problem, while still being runnable? Also include any sample input, the expected output for that input, and the actual output you're getting instead, including any error messages, each within <code> tags. The aim is to provide a piece of code that we can simply download and run, and that reproduces the problem - you'll get help fastest that way. Often, this process will also help you see what the issue might be.

        I think this works, but why does it stop to work, when I make it writing instead of reading and return()ing instead of die()ing?

        Same thing, I'd have to see the actual code you're running to say more. See also How do I post a question effectively?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11101758]
Approved by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2020-02-18 06:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What numbers are you going to focus on primarily in 2020?










    Results (75 votes). Check out past polls.

    Notices?