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

Hello there,

I'm using the following piece of code under Win2k to create a directory but it's returning me an "Invalid argument" error message. Am I using the wrong parameter for the mkdir funcion?

$label = `date /t`;

$label=~ s/.*\s(\d+)\/(\d+)\//\1\2/;

$dir = "Processed_$label";

mkdir ($dir, 0777) || die "$!";

Thanks, Robert

Replies are listed 'Best First'.
(Ovid - let's improve your regex) Re: Directory
by Ovid (Cardinal) on Jan 15, 2001 at 21:54 UTC
    Also, your regular expression has some issues. Let's improve it incrementally. The value I get in $label at the current time is Mon 01/15/2001. Assuming that's correct, let's patch this up:

    1. You have two forward slashes '/' escaped. Rather than escape them, change the delimeters on the substitution for clarity:
      $label=~ s#.*\s(\d+)/(\d+)/#\1\2#;
      Right off the bat, we have a huge improvement in terms of "readability".
    2. \1 and \2 should not be in the right side of a substitution. They are used within a regular expression to identify a backreference. This implies to me that you are not using warnings. If you are, you get a message like "\1 better written as $1." Let's go ahead and change those:
      $label=~ s#.*\s(\d+)/(\d+)/#$1$2#;
      Not only does that eliminate the warning, it gets rid of a couple of escapes that might obscure the meaning to a novice programmer.
    3. And finally (you old-timers knew I was going to bring this up :-), you have a dot star '.*' in your regex. While dot star is sometimes useful (when you're slurping up the rest of a string, for example), this combination usually kills the efficiency of a regular expression. My usual comment: see Death to Dot Star! for details of this. Change the dot star to a negated character class (or a non-whitespace metacharacter '\S', in this case). If you are iterating over this expression, you may see a significant performance increase.
      $label=~ s#\S*\s(\d+)/(\d+)/#$1$2#;

    We went from this:

    s/.*\s(\d+)\/(\d+)\//\1\2/;
    To this:
    s#\S*\s(\d+)/(\d+)/#$1$2#;
    It might not seem like much for such a small regex, but as they get more complicated, such small changes can make a world of difference.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

(tye)Re: Directory
by tye (Sage) on Jan 15, 2001 at 21:35 UTC

    It looks like you are leaving the newline on the end of $label, which isn't an allowed character in a file name under Win32.

            - tye (but my friends call me "Tye")
Re: Directory
by lemming (Priest) on Jan 15, 2001 at 21:31 UTC
    In all likelyhood, it's choking on your date command. Check to see if you have any new directories with odd names.
    Instead of calling an outside program, how about using localtime() or one of the Date modules?

    Update: Despite tye probably caqlling it correctly, I'll stand by my suggestions. You might want to call the full path to the date program if you insist on an outside call. After all, how can you be sure you'll get the right one?

      Or POSIX::strftime

      --
      <http://www.dave.org.uk>

      "Perl makes the fun jobs fun
      and the boring jobs bearable" - me

Re: Directory
by extremely (Priest) on Jan 15, 2001 at 21:46 UTC
    You might need to look at File::Path for a more flexible way to make dirs. Also, look at localtime and sprintf for making that label without shelling out. $label = sprintf "%02d%02d", (localtime)[4,3] works except that months are returned as 00-11 rather than 01-12.

    --
    $you = new YOU;
    honk() if $you->love(perl)

Re: Directory
by I0 (Priest) on Jan 15, 2001 at 22:49 UTC
    chomp $label;