Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

How to build system calls using '=>'

by loris (Hermit)
on Dec 14, 2005 at 13:10 UTC ( [id://516617]=perlquestion: print w/replies, xml ) Need Help??

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

I came across Re: "mkdir -p" equivalent? which contains the following:

system mkdir => '-p' => @dirs;

which I didn't understand. So I looked at perlop but didn't really understand that either. However, even without working out what was going on, I thought either

system mkdir => '-m 775 -p' => @dirs;

or

system mkdir => '-m 775' => '-p' => @dirs;

would work, but neither does. Both produce

mkdir: invalid mode

Can anyone shed a little light on what is going on here?

Yours benightedly,

loris


"It took Loris ten minutes to eat a satsuma . . . twenty minutes to get from one end of his branch to the other . . . and an hour to scratch his bottom. But Slow Loris didn't care. He had a secret . . ."

Replies are listed 'Best First'.
Re: How to build system calls using '=>'
by Perl Mouse (Chaplain) on Dec 14, 2005 at 13:18 UTC
    A => is also called a "fat comma". It's basically a comma, but if the left hand side looks like a 'bare word', it assumes it's quoted. So,
    system mkdir => '-p' => @dirs
    is just a fancy way of writing:
    system 'mkdir', '-p', @dirs
    There are some people who like to use => instead of a comma to separate arguments that have different roles.
    system mkdir => '-m 775' => '-p' => @dirs;
    That indeed doesn't work. Because system has a list of arguments, no shell is involved, so mkdir is called, with -m 755 as a single argument. It should be two. Either use:
    system 'mkdir', '-m', '775', '-p', @dirs;
    or
    system mkdir => -m => 775, -p => @dirs;
    or, if you have sure @dirs doesn't contain any characters special to the shell:
    system "mkdir -m 775 -p @dirs";
    Perl --((8:>*
Re: How to build system calls using '=>'
by Corion (Patriarch) on Dec 14, 2005 at 13:14 UTC

    The => operator is called "fat comma", because it mostly acts like a comma. So, in effect, the system call is equivalent to:

    system( 'mkdir', '-p', @dirs );

    Note that the call to system uses the system LIST form. Looking at [perlfunc://system], you will see that this form bypasses any parameter parsing by the shell.

    Your solution tried to pass the "-m 775" switch, but mkdir only knows about the "-m" switch with the value 775. That is the thing which is different.

Re: How to build system calls using '=>'
by serf (Chaplain) on Dec 14, 2005 at 14:00 UTC
    I appreciate that you're just using "mkdir -p" as an example here... but for any passers by who are hunting for a way to make a path of directories they would be better following blue_cowdawg's advice in Re: "mkdir -p" equivalent? and using mkpath in File::Path

    If they have a reason they can't use File::Path (even though it's a core module these days) they would be better using the built-in mkdir than shelling out to a system one.

    use strict; use warnings; my $seperator = '/'; # Change this for a non-Unix compatible OS my @dirs = ("some/long/dir/path"); for my $path ( @dirs ) { my @path = split($seperator, $path); my $cat_path; for my $dir (@path) { $cat_path .= $dir; unless ( -d $cat_path ) { mkdir ( $cat_path ) || die "Can't mkdir '$cat_path': $!\n"; print "mkdir: created directory `$cat_path'\n"; } $cat_path .= $seperator; } }
    and Three has dealt with some of the problems faced by Windows users in Re: Perl API that emulates mkdir -p on unix? (yes, for *Windows*) :o)
      ..or any passers by who are hunting for a way to make a path of directories they would be better following blue_cowdawg's advice in Re: "mkdir -p" equivalent? and using mkpath in File::Path
      I always wonder how useful statements like "it's better to use X instead of Y" are if they don't say why X is better.

      I'll bite. I say using the systems 'mkdir' is better than 'mkpath' because the arguments of 'mkpath' are hard to remember (without looking in the docs, what's the second argument of mkpath? How do I tell mkpath which mode I need? How do I create multiple directories in one go?). On top of that, 'mkpath' has a different name than 'mkdir'.

      Sure, if you work on a system that doesn't have 'mkdir', you're better off to use File::Path. But then, programming in such an environment is like writing a novel without using the letter 'e'.

      If they have a reason they can't use File::Path (even though it's a core module these days) they would be better using the built-in mkdir than shelling out to a system one.
      And then you present a 17 line piece of code, which has a OS dependency as well, doesn't have an option to set a mode, and is verbose without an option to turn it off.

      I strongly prefer to shell out using one line, have the ability to set the mode, and which, by default, is silent.

      Perl --((8:>*
        Why: mkpath doesn't require an external binary, doesn't create another process to do its job, and has full control over what it's doing and what comes back - there are less places that the attempt to create a directory can go wrong.

        Re remembering: The link to blue_cowdawg's advice in Re: "mkdir -p" equivalent? is there specifically because it *shows* an example of how to use mkpath, including modes etc - so they don't *have* to remember.

        The 17 line piece of code is an _example_. It is verbose so that the user knows where to report if they need to do so, they can always comment out the print, but it's where it is so they know if they want to report, that's *where* they should do it, i.e. it should only say it's done it once it's worked and not before.

        Shelling out to 'mkdir -p $path' is OS dependent as well - if you do that on Windows (tested on xp) you will end up with a directory called "-p" as well. In the example it points out *where* to change the directory seperator.

        mkdir allows you to set the mode as well, if you wish to - fair call, perhaps I could have added that in the example. :o)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://516617]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2024-04-25 23:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found