Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic


by Anonymous Monk
on Apr 17, 2003 at 14:14 UTC ( #251209=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi! I'd like to create a path under GNU/Linux with Perl:
use File::Path; mkpath("/var/tmp/log/script/",0,1777);
This should give the following result:
[thom@marvin] $ ls -l /var/tmp/log drwxrwxrwt 2 thom thom 4096 Apr 17 14:25 script
But really gives the following:
[thom@marvin] $ ls -l /var/tmp/log d-wx-----T 2 thom thom 4096 Apr 17 14:25 script
What am I doing wrong? Thanks, Thom

Replies are listed 'Best First'.
Re: mkpath()
by Improv (Pilgrim) on Apr 17, 2003 at 14:19 UTC
    You need the heading 0 to make sure perl knows that you're giving it an octal value
    Update: You should also follow perlplexer's advice above, and do a umask(0) before calling this. If you want it to be minimally intrusive on the rest of your program, try something like this:
    sub my_mkpath { my ($path, $mask) = @_; my $ok = 1; my $save_u = umask(); umask(0); eval(mkpath($path, 0, oct($mask))); if($@) # mkpath failed! {warn "Couldn't create $path: $@"; $ok=0;} umask($save_u); return $ok; }

      This helped, but just a little bit:

      drwx-----T 2 thom thom 4096 Apr 17 16:28 script

      Thanks, Thom

      Thanks Improv! This works.

      But I still don't understand why I have to set the umask to oct 0...

      Anyway, at least the code works now.

      I sort of golfed this down to the following ( I added a bit of whitespace here to make it more reable, but i get 100 chars for the block part of the sub :-)

      use File::Path; use warnings::register; sub umask_mkpath { my@c; umask((umask(shift),@c=eval{mkpath(@_)} or warnings::warnif "Err:$@")[0]); @c }

      I omitted the string to numeric conversion you were doing with oct(), because I felt the caller was more likely to know if this was needed or not, and I added the ability it set the umask (the first argument). Otherwise this should behave like mkpath(), expect that if it returns false, the error message will be in $@.

      Incidentally I did this mostly because your code reminded me of a trick i'd seen before that avoids using a temporary variable when setting an attribute on a different filehandle without changing the currently selected one.

      select((select(STDERR),$|++)[0]); # autoflush STDERR

      And I thought I might try to apply the idiom here. Anyway. :-)


      <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
Re: mkpath()
by perlplexer (Hermit) on Apr 17, 2003 at 14:17 UTC
    Check what umask is set to and change it if necessary.


      umask() returns 63

      But why do I have to set an umask, if I give a mode? I don't have to set a special umask if I use "mkdir -m 1777" on the shell.

      Thanks, Thom

        From 'perldoc -f umask':

        "permission (or "mode") values you pass mkdir or sysopen are modified by your umask, so even if you tell sysopen to create a file with permissions 0777, if your umask is 0022 then the file will actually be created with permissions 0755"

        So, unless mkpath() does some trickery with umask() by itself, the mode that you pass to mkpath() will be affected by current value of umask().

        And make sure you prepend the mode with '0', as Improv++ already mentioned.

Re: mkpath()
by Anonymous Monk on Feb 26, 2014 at 14:24 UTC
    (Added for reference for googlers) mkpath is legacy, try make_path, works as you wanted.
    use File::Path qw(make_path) make_path("/var/tmp/log/script/",{mode => 0777});

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://251209]
Approved by broquaint
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2017-05-26 15:35 GMT
Find Nodes?
    Voting Booth?