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

The following line copies files from one directory to the other only if it is newer.
system("cp -u $copy_from $copy_to");
I'm curious to know what the "right" way of doing this is, without relying on the 'system' command. File::Copy doesn't do it. Yeah, it'd be easy enough to roll my own but it just seems strange that I should have to. I'm curious to know where the lazy way might lie.

Also, just how "wrong" is it to use the 'system' command. Not portable and no easy way to verify success of the command. Anything else?

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff";
$nysus = $PM . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: Duplicating the 'cp' command's '-u' switch
by Roger (Parson) on Dec 10, 2003 at 03:03 UTC
    You can use the built-in stat function to determine the modification time of a file.
    use strict; use warnings; my $from = "first.txt"; my $to = "new.txt"; copy_if_newer($from, $to); sub copy_if_newer { my ($from, $to) = @_; # test for file modification time return 0 if (stat $from)[9] <= (stat $to)[9]; # do the actual file copy here with File::Copy, etc. # return 1 to indicate success return 1; }
      Forgot about that function. Easy enough. Maybe I'm being too lazy. :)

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff";
      $nysus = $PM . $MCF;
      Click here if you love Perl Monks

Re: Duplicating the 'cp' command's '-u' switch
by Abigail-II (Bishop) on Dec 10, 2003 at 10:27 UTC
    Also, just how "wrong" is it to use the 'system' command.
    IMO, there's nothing wrong with the system command. I prefer using system cp => $file1, $file2 over using File::Copy::copy as well, as the first will do what it is supposed to do, and the latter will be a surprise when it comes to permission bits. Furthermore, cp can take options, more than 2 arguments, directories as arguments, etc, none of which is supported by File::Copy::copy.

    People who claim File::Copy::copy is the way to do cp in Perl clearly don't know cp!

    As for portability, I think that the majority of the Perl programs are written to operate in a specific environment, where portability isn't an issue at all. Besides, the GNU implementation of cp supports -u, which means you're ok for (allmost?) Unix and most Windows flavours.

    Abigail

Re: Duplicating the 'cp' command's '-u' switch
by Zaxo (Archbishop) on Dec 10, 2003 at 07:12 UTC

    Here,

    use File::Copy; sub ucopy { @_ == 2 or die 'sub ucopy needs two arguments.'; -e $_[1] and (stat $_[1])[9] > (stat $_[0])[9] and return 1; copy @_; }
    The first statement in the sub checks for the proper number of arguments. The second returns success without doing anything if the target exists and is newer than the source (by mtime). If that didn't happen, &File::Copy::copy is called on the arguments and its result returned.

    After Compline,
    Zaxo

Re: Duplicating the 'cp' command's '-u' switch
by sauoq (Abbot) on Dec 10, 2003 at 19:54 UTC
    Also, just how "wrong" is it to use the 'system' command. Not portable and no easy way to verify success of the command.

    No easy way to verify success? Huh? Check $? (or the return value from the system call) and, if it is zero you succeeded. If it is negative, check $! or if it is positive and you need more information, do the appropriate shifts and bitwise-ands on $? to get it.

    Sure, it requires a slightly different approach than the copy(...) or die $! but it's still easy to do.

    -sauoq
    "My two cents aren't worth a dime.";