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

Greetings O wise ones,

I am trying to capture the output of the "mkdir savehere" command, but dont know the possible errors that could be thrown [other that subdirectory already exists], could there be one due to size or permissions??

Anyway all im trying to do is continue with script execution in case of a "pass"/"subdirectory already exists"[That ones fine, will have to print a warning and continue], but stop script execution after printing an error message if any other error is encountered.

Right now im pattern matching for outputs of the command, but dont know any of the other error messages :(,

my $op = `mkdir winlog`; if ($op =~ /already exists/i) { print "Warning : folder already exists."; }

Please Help!!

Replies are listed 'Best First'.
Re: Handling returns from mkdir.
by Corion (Patriarch) on Dec 24, 2010 at 08:51 UTC

    Why not use mkdir directly?

    Or even -d (and -l) if you really need to check for existence yourself, instead of simply trying to create the directory and judging success by its results.

      Good point. But remember that TOCTOU might be a problem. mkdir $directory, check $!, and ignore EEXIST ("File exists"). After that, $directory may still be something non-directory, but you will know that when chdir $directory or open(...,"$directory/filename") fails with ENOTDIR ("Not a directory").

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

      Thanks for the help (Im trying to keep this code same for linux and windows, so im scared to use any options)

      my $err = `mkdir $FolderName 2>&1`; chomp ($err); if ($? != 0) { if ($? == 256) { print "Warning : $err"; } else { print "Error : $err"; } }

      That part of the code now works like a charm :)

        Im trying to keep this code same for linux and windows, so im scared to use any options

        One more reason NOT to use an external mkdir. Perl's builtin function works the same everywhere. "2>&1" doesn't work on all Windows versions, so you can't use it according to your rules. $FolderName is not quoted properly, this will bite you soon. Remember that you need to quote differently on Windows and Linux, because you have different shells. Don't think that quoting rules are the same for all shells that you might see on Linux. bash is the most common shell on Linux, but it's not the only one.

        Short: Use the buildin mkdir function. It is faster, cleaner, and opens no security holes.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Handling returns from mkdir.
by cdarke (Prior) on Dec 24, 2010 at 11:54 UTC
    To find out the errors from an external command, like mkdir, then you should read the doocumentation for that command. For mkdir(1) the POSIX standard gives two possible return codes, 0 (success) and >0 (failure), but does not mention error messages. The man pages on Linux don't give any more information.

    For built-ins like mkdir, they are (mostly) based on the C API of the same name, so we look at sections 2 and 3 of the man pages, for example:
    man 2 mkdir
    This will usually give a list of error numbers from $! which can be tested for (the POSIX standard is similar). These are exposed within Perl through the Errno module. The POSIX standard lists: EACCES, EEXIST, ELOOP, EMLINK, ENAMETOOLONG, ENOENT, ENOSPC, ENOTDIR, EROFS, but your UNIX/Linx implememtation could have more.

    On Windows, mkdir /? gives no information on errors. For the C interface, consult the MSDN mkdir, which only lists EEXIST and ENOENT as possible errors. However, that does make the assumption that your Windows implementaion uses the POSIX mkdir or ISO C _mkdir, it could be using the Win32 API CreateDirectory instead. The good news on that though is that the possible errors are similar to mkdir.
Re: Handling returns from mkdir.
by samarzone (Pilgrim) on Dec 24, 2010 at 08:32 UTC

    mkdir does not give any standard output. In case of failure of mkdir you see the error output which is not returned by backtick (``) operators. You may have to redirect error output to standard output to capture it.

    my $op = `mkdir winlog 2>&1`;

    On my system the error message in case of pre-existence of directory is "cannot create directory `winlog': File exists" which will fail your regular expression. I think using the return codes is a better idea than using the error output. You can get the return code in $?

    For all codes returned by the mkdir check the detailed manual of the command

    Update: As pointed by corion and marto below mkdir of perl is the correct option. My answer is more concerned with the way of getting output rather than the approach.

    --
    Regards
    - Samar

      Perl has a mkdir function built in, there's no need to rely on an external command.

        Hi marto,

        Thats actually what I was looking for..managed to use the built in command instead.

        I have been trying to find other errors reported by $!(File exists being the only one that kept coming up with the code), without any luck.

        I know this sounds pretty silly but, can you please tell me how i can find them(maybe a list of some sort)....im still a newbie.

        Thanks for all the help so far!!

        You are right. In the above answer I was just concerned with the way of output. I should have thought on the approach itself.

        Thanks marto.

        --
        Regards
        - Samar
Re: Handling returns from mkdir.
by Khen1950fx (Canon) on Dec 24, 2010 at 12:25 UTC
    I tried this with File::Path. It'll return "mkdir winlog" on success, undef if file already exists, or a message if something else went wrong.
    #!/usr/bin/perl use strict; use warnings; use File::Path qw(make_path); my $dir = 'winlog'; make_path( $dir, { verbose => 1, mode => 0711, } ); open STDOUT, '<', $dir or die "Couldn't open $dir: $!\n";