Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Why can't I open a file for writing?

by tdilling (Initiate)
on Jan 12, 2018 at 21:39 UTC ( #1207168=perlquestion: print w/replies, xml ) Need Help??
tdilling has asked for the wisdom of the Perl Monks concerning the following question:

I have used perl pretty extensively in the past for file/text manipulation. So this should be straightforward. My code reads a list of files from a directory into an array (via a glob), then iteratively goes through each one and makes a modified copy in a sub-directory. Straightforward stuff. I've simplified the code down a bit in the example below:

my $dir = '/some/directory/here'; my @files = <$dir/\d{6}*>; # All the relevant files start with 6 n +umbers, so don't glob others! foreach (@files) { $inputfile = $_; [open $inputfile for reading, this code works fine] .... $outputfile = $inputfile; open NEWFILE, '>', "$dir/subdirectory/$outputfile" | die "Can't +open $dir/subdirectory/$outputfile for writing: $!"; ..... }

Any thoughts? I get the following error: "Cannot open /some/directory/here/subdirectory/314767_TJD_Appr5000_2017-01-06_13_10_03.txt for writing: at line 48.

Yes, I know the filename is somewhat long and convoluted, but it is what it is. :-)

Thanks for your guidance!

Replies are listed 'Best First'.
Re: Why can't I open a file for writing?
by Perlbotics (Chancellor) on Jan 12, 2018 at 21:42 UTC

    Perhaps the bitwise or (|)?

    open NEWFILE, '>', "$dir/subdirectory/$outputfile" | die "Can't open + $dir/subdirectory/$output here-^
    Try or or || instead.

      Arrrgh! That fixed it. That's what happens when you stare at the same line of code for too long... LOL

        If you use || instead of or then you need parentheses for the open function:

        open( NEWFILE, '>', "$dir/subdirectory/$outputfile" ) || die "Can't +open $dir/subdirectory/$output
Re: Why can't I open a file for writing?
by haukex (Abbot) on Jan 13, 2018 at 09:09 UTC

    Something I noticed in addition to the comments about open ... or die:

    my $dir = '/some/directory/here'; my @files = <$dir/\d{6}*>; # All the relevant files start with 6 numbers, so don't glob others!

    Sorry but I don't see how the pattern <$dir/\d{6}*> can be working at all* - glob does not recognize regex syntax, unless you're using some custom module. Always Use strict and warnings - you should be seeing a warning like "Unrecognized escape \d passed through".

    Also, be very careful with what $dir contains, and in fact with glob in general, as discussed in the recent thread To glob or not to glob.

    * Update: Or rather, how it is working in the context provided, "All the relevant files start with 6 numbers" - thanks for pointing this out, Lotus1!

      Like you said there will be a warning but the pattern will match files. It matches files starting with 'd6' with any number of characters after it. I imagine the next question after fixing the file open issue would have been 'why are only some files being opened?'

      use warnings; use strict; use v5.10; say foreach glob("\d{6}*"); __END__ Unrecognized escape \d passed through at line 5. d60000000000b.txt d600.txt
Re: Why can't I open a file for writing?
by Laurent_R (Canon) on Jan 13, 2018 at 15:48 UTC
    In addition to what other monks have already said, please note that glob "*" or <$dir/*> will return a list of files with their path. So, @files will contain things such as /some/directory/here/foo.txt. This is OK for reading the files in the foreach loop (and this is often what you want), but this:
    $outputfile = $inputfile; open NEWFILE, '>', "$dir/subdirectory/$outputfile" or die "... $!" +;
    will probably fail, or, at the very least, not work as expected, because the new file to be created will look like /some/directory/here/subdirectory/some/directory/here/foo.txt which is presumably not what you want. So you probably to extract the file name (without the path) before assigning outputfile or use some other means for creating the list of files.

      BTW, you might also try

      use strict; use warnings, use autodie; open my $new_file, '>', qq($dir/subdirectory/$outputfile);

      ...instead of open NEWFILE, '>', "$dir/subdirectory/$outputfile" || die qq(Crap: $!)

      See also Why the Modern Perl Book Avoids Bareword Filehandles and autodie.

      Best regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

      perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1207168]
Approved by Perlbotics
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2018-06-24 10:44 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (126 votes). Check out past polls.