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

I have the following code:

#!/usr/bin/perl -w use strict; my $name = "Zenon Zabinski"; my $date = "072800"; open(FILE, "folder/${name}/${date}.txt"); print FILE "test"; close FILE;

... and it doesn't work. I thought that maybe it couldn't open a file with a number for a name so I changed the value of $date to "date", but that didn't help.

Using a space in the path didn't seem to be a problem when I put Zenon Zabinski directly into the path, but I need it to come from a variable.

Sooooooooo, what is the problem??

Thanks.

Zenon Zabinski | zdog | zdog7@hotmail.com

P.S. Wups! I almost forgot. I keep getting the following warning when I run this:

print() on closed filehandle main::FILE at test.pl line 10.

Replies are listed 'Best First'.
RE: More File/Directory Trouble
by autark (Friar) on Jul 29, 2000 at 01:22 UTC
    Maybe you should open the file for writing ?
    open(FILE, ">folder/${name}/${date}.txt") || die "Unable to open file, reason: $!\n";
    Autark.
      That worked perfectly. Thanks again.

      Zenon Zabinski | zdog | zdog7@hotmail.com

RE: More File/Directory Trouble
by mikfire (Deacon) on Jul 29, 2000 at 05:31 UTC
    Sigh. Others have answered the question and I am ( once again ) simply throwing pop bottles from the bleachers.
    open(FILE, ">folder/${name}/${date}.txt");
    Why are you doing this? I know, you are making sure Perl Does the Right Thing and you have been bitten by ( I am guessing here ) shell programming.

    In Perl, legal variables names are must start with an alphabetic character or an underscore. After that, it can be lots of things. It cannot be, though, / or ".". Which means you can write that line as

    open(FILE, ">folder/$name/$date.txt");
    which is easier on my poor eyes. It flows, it makes sense.

    Of course, I also fall off the end of this statement. Especially when you open it for writing. You are not checking to see if you open the file. This will annoy you later, believe me. A wise monk ( or at least a monk who is tired of being bitten by this ) would say

    open(FILE, ">folder/$name/$date.txt") || die("Couldn't open file for w +riting: $!");
    which will not only protect you from trying to write to an unopened file, but it will also tell you why it didn't work.

    Of course, a stylish monk would take offense to all the parens in there. Actually, a stylish monk is really lazy and hates the cording necessary to make ( and ). So s/he would say instead

    open FILE, ">folder/$name/$date.txt" or die "Couldn't open file for re +ading:$!";
    I would take this one step further and make the error message more informative and say
    my $filename = "folder/$name/$date.txt"; open FILE, ">$filename" or die "Couldn't open $filename for writing: $ +!";
    This would tell me what the code was trying to open so I could figure out what I screwed up this time.

    mikfire

      While you're correct that the {brackets} around the variables aren't necessary in this case, they're still perfectly legal and necessary in cases where ambiguity exists.
      $var = "${one}two$three"; # "1two3" $var = $one . "two$three"; # "1two3"
      Certainly both of these methods achieve the same result, but there are instances when putting two variables together in a double-quoted string is more legible or needed for other reasons. In these cases, surrounding the variable name in brackets is necessary.
        Sometimes the posting code in perlmonks annoys me. Chalk it up to inexperience I guess. See the next post, which I would have preferred would replace the one I'm replying to here.

        Why can't there be a delete function? Heh.

      Ignore this post -- I misread your comment as chastizing the poster for using ${shell} style variables that "weren't" supported in Perl. You are absolutely right and the explanation was good.

      While you're correct that the {brackets} around the variables aren't necessary in this case, they're still perfectly legal and necessary in cases where ambiguity exists.

      $var = "${one}two$three"; # "1two3" $var = $one . "two" . $three; # "1two3"
      Certainly both of these methods achieve the same result, but there are instances when putting two variables together in a double-quoted string is more legible or needed for other reasons. In these cases, surrounding the variable name in brackets is necessary.
Re: More File/Directory Trouble
by athomason (Curate) on Jul 29, 2000 at 01:40 UTC
    The default access mode when you pass only a string to open is reading. From perldoc -f open:
    If MODE is `'<'' or nothing, the file is opened for input. If MODE is `'>'', the file is truncated and opened for output, being created if necessary. If MODE is `'>>'', the file is opened for appending, again being created if necessary. You can put a `'+'' in front of the `'>'' or `'<'' to indicate that you want both read and write access to the file; thus `'+<'' is almost always preferred for read/write updates--the `'+>'' mode would clobber the file first. You can't usually use either read-write mode for updating textfiles, since they have variable length records. See the -i switch in the perlrun manpage for a better approach. The file is created with permissions of `0666' modified by the process' `umask' value.
RE: More File/Directory Trouble
by Anonymous Monk on Jul 31, 2000 at 21:25 UTC
    There's another issue here that nobody has spotted - perl won't make the intermediate directories if you try and open foo/bar/baz.dat - you'll get a "No such file or directory" error. If this is part of code that gets other values of $name from somewhere, you'll have to make the directories with perlfunc 'mkdir' first. Baz