open files.

Discussion in 'Perl Misc' started by BeHealthy@gmail.com, Oct 4, 2005.

  1. Guest

    If I use open(fp, $FILENAME), where $FILENAME contains some
    subdirectory that hasn't been set up yet, then it fails. Is there any
    way I can get around this by letting the program to create the
    subdirectory if needed?
     
    , Oct 4, 2005
    #1
    1. Advertising

  2. Paul Lalli Guest

    wrote:
    > If I use open(fp, $FILENAME), where $FILENAME contains some
    > subdirectory that hasn't been set up yet, then it fails.


    open() is not used for directories, it is used for files.
    perhaps you're thinking of 'opendir()'?

    > Is there any
    > way I can get around this by letting the program to create the
    > subdirectory if needed?


    Your algorithm needs some rethinking. You're opening a directory. If
    you want to use an analogy to opening files, you're opening the
    directory "for reading". There is no such thing as opening a directory
    "for writing". If the directory doesn't exist, even if there were a
    built-in way to make open auto-create the directory, it would be
    created empty. You would then have nothing to read from it.

    It's time for you to tell us what you're *actually* trying to
    accomplish, rather than ask for help with the method you've already
    decided to use to accomplish this unknown goal.

    FWIW, I don't see any particular reason you can't just do:
    -d $directory_name or mkdir $directory_name
    or die "Couldn't create directory $directory_name: $!\n";

    (with the possible exception of the chance of a race condition)

    Paul Lalli
     
    Paul Lalli, Oct 4, 2005
    #2
    1. Advertising

  3. Babacio Guest

    "Paul Lalli"

    > wrote:
    >> If I use open(fp, $FILENAME), where $FILENAME contains some
    >> subdirectory that hasn't been set up yet, then it fails.

    >
    > open() is not used for directories, it is used for files.
    > perhaps you're thinking of 'opendir()'?


    I think that what the OP means is that $filename =
    '/tmp/nonexists/file.txt', for example, and he wants write in it; so
    if the file does not exists, the file should be created, but of course
    this does not work if the directory '/tmp/nonexists/' does not exist.

    May be there is something on CPAN to do that, but it's not a very
    difficult thing to write anyway.
    --
    Bé erre hue ixe eu elle, Bruxelles.
     
    Babacio, Oct 4, 2005
    #3
  4. Paul Lalli Guest

    Babacio wrote:
    > Note: The author of this message requested that it not be archived. This
    > message will be removed from Groups in 6 days (Oct 11, 2:38 pm).


    Please don't do that. It's rude.

    > "Paul Lalli"
    >
    > > wrote:
    > >> If I use open(fp, $FILENAME), where $FILENAME contains some
    > >> subdirectory that hasn't been set up yet, then it fails.

    > >
    > > open() is not used for directories, it is used for files.
    > > perhaps you're thinking of 'opendir()'?

    >
    > I think that what the OP means is that $filename =
    > '/tmp/nonexists/file.txt', for example, and he wants write in it; so
    > if the file does not exists, the file should be created, but of course
    > this does not work if the directory '/tmp/nonexists/' does not exist.


    Hrm. I can see that interpretation.

    > May be there is something on CPAN to do that, but it's not a very
    > difficult thing to write anyway.


    I don't know if there's a module on CPAN to do exactly that, but as you
    say, it's not overly difficult to write a subroutine that will do it,
    especially if we take advantage of a certain module that does exist:

    #!/usr/bin/perl
    use strict;
    use warnings;
    use File::Spec;

    sub open_or_make(\$$){
    my ($fh_ref, $path) = @_;
    my ($v, $dirs, $file) = File::Spec->splitpath($path);
    my @dirs = File::Spec->splitdir($dirs);
    my $dir;
    while (my $curdir = shift @dirs){
    $dir = $dir ? File::Spec->catdir($dir, $curdir) : $curdir;
    -d $dir or mkdir $dir or return undef;
    }
    open $$fh_ref, '>', $path or return undef;
    return 1;
    }

    my $filename = 'temp/nothere/subdir/file.txt';
    open_or_make my $ofh, $filename
    or die "Could not open or make $filename: $!\n";
    print $ofh "Hello World\n";
    close $ofh;
    __END__

    Paul Lalli
     
    Paul Lalli, Oct 4, 2005
    #4
  5. Babacio Guest

    "Paul Lalli"

    >> Note: The author of this message requested that it not be archived. This
    >> message will be removed from Groups in 6 days (Oct 11, 2:38 pm).

    >
    > Please don't do that. It's rude.


    Mmmh, I have my own opinion on this subject, sorry.
    But I may make an exception for this group, in fact.
    I'll think of it.

    > I don't know if there's a module on CPAN to do exactly that, but as
    > you say, it's not overly difficult to write a subroutine that will
    > do it,


    I did not try, because I knew that you were going to do that in just a
    blink. You're darn too fast!

    > especially if we take advantage of a certain module that does exist:
    >
    > #!/usr/bin/perl
    > use strict;
    > use warnings;
    > use File::Spec;


    Well, stupidely enough, I knew File::Basename but not File::Spec. It
    seems quite more complete.

    > sub open_or_make(\$$){
    > my ($fh_ref, $path) = @_;
    > my ($v, $dirs, $file) = File::Spec->splitpath($path);
    > my @dirs = File::Spec->splitdir($dirs);
    > my $dir;
    > while (my $curdir = shift @dirs){
    > $dir = $dir ? File::Spec->catdir($dir, $curdir) : $curdir;


    Both tricky and elegant.

    > -d $dir or mkdir $dir or return undef;
    > }
    > open $$fh_ref, '>', $path or return undef;
    > return 1;
    > }
    >
    > my $filename = 'temp/nothere/subdir/file.txt';
    > open_or_make my $ofh, $filename
    > or die "Could not open or make $filename: $!\n";
    > print $ofh "Hello World\n";
    > close $ofh;
    > __END__
    >
    > Paul Lalli


    Bravo.
    --
    Bé erre hue ixe eu elle, Bruxelles.
     
    Babacio, Oct 4, 2005
    #5
  6. Paul Lalli Guest

    Babacio wrote:
    > "Paul Lalli"
    >
    > >> Note: The author of this message requested that it not be archived. This
    > >> message will be removed from Groups in 6 days (Oct 11, 2:38 pm).

    > >
    > > Please don't do that. It's rude.

    >
    > Mmmh, I have my own opinion on this subject, sorry.


    Don't apologize. You're entitled to your opinion. Just as I'm
    entitled to add you to my kill file until what I perceive as your
    rudeness has ended.

    Fare thee well.
     
    Paul Lalli, Oct 4, 2005
    #6
  7. Babacio Guest

    "Paul Lalli"

    >> >> Note: The author of this message requested that it not be archived. This
    >> >> message will be removed from Groups in 6 days (Oct 11, 2:38 pm).
    >> >
    >> > Please don't do that. It's rude.

    >>
    >> Mmmh, I have my own opinion on this subject, sorry.

    >
    > Don't apologize. You're entitled to your opinion. Just as I'm
    > entitled to add you to my kill file until what I perceive as your
    > rudeness has ended.


    Of course, no problem for me.

    --
    Bé erre hue ixe eu elle, Bruxelles.
     
    Babacio, Oct 4, 2005
    #7
  8. Paul Lalli wrote:

    > my @dirs = File::Spec->splitdir($dirs);
    > my $dir;
    > while (my $curdir = shift @dirs){
    > $dir = $dir ? File::Spec->catdir($dir, $curdir) : $curdir;
    > -d $dir or mkdir $dir or return undef;
    > }


    I think File::path may help to simplify the above.
     
    Brian McCauley, Oct 4, 2005
    #8
  9. Paul Lalli Guest

    Brian McCauley wrote:
    > Paul Lalli wrote:
    >
    > > my @dirs = File::Spec->splitdir($dirs);
    > > my $dir;
    > > while (my $curdir = shift @dirs){
    > > $dir = $dir ? File::Spec->catdir($dir, $curdir) : $curdir;
    > > -d $dir or mkdir $dir or return undef;
    > > }

    >
    > I think File::path may help to simplify the above.


    Whoa. Indeed it would. Why didn't I know about this module?

    Many thanks, Brian.

    Paul Lalli
     
    Paul Lalli, Oct 4, 2005
    #9
  10. Joe Smith Guest

    Parents of files to be opened

    wrote:
    > If I use open(fp, $FILENAME), where $FILENAME contains some
    > subdirectory that hasn't been set up yet, then it fails. Is there any
    > way I can get around this by letting the program to create the
    > subdirectory if needed?


    If you are opening a file for output, you should have said so.

    Just get the directory part of $FILENAME and then recursively
    (or iteratively) create the parent directory if needed.
    -Joe


    sub mkdir_p { # Like 'mkdir -p', create parent if needed
    my($parent,$success);
    foreach my $dir (split '/',$_[0]) {
    $parent .= $dir;
    next if $parent eq '' or -d $parent;
    ($success = mkdir $parent,0777) or
    (warn "mkdir('$parent') failed: $!\n" and return 0);
    } continue {
    $parent .= '/';
    }
    $success; # True if dir needed to be created and was created
    }

    ....
    my $newname = "$dst/$name";
    my ($dir) = $newname =~ m{(.*)/};
    print "mkdir $dir\n" if mkdir_p $dir and $verbose;
    open my $fh,'>',$newname or die "...";
     
    Joe Smith, Oct 5, 2005
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Shilpa
    Replies:
    1
    Views:
    6,047
    Anubhav Jain
    Mar 22, 2006
  2. THY
    Replies:
    4
    Views:
    517
    Gönen EREN
    Aug 22, 2003
  3. crazyprakash
    Replies:
    4
    Views:
    3,376
    adrian
    Oct 30, 2005
  4. Replies:
    4
    Views:
    957
    M.E.Farmer
    Feb 13, 2005
  5. Replies:
    3
    Views:
    1,466
    Rolf Magnus
    Jan 18, 2009
Loading...

Share This Page