views:

6419

answers:

4

What is the best way in Perl to copy files to a yet to be created destination directory tree?

Something like

copy("test.txt","tardir/dest1/dest2/text.txt");

wont work since the directory tardir/dest1/dest2 does not yet exist.

What is the best way to copy with directory creation in Perl?

+4  A: 
use File::Basename qw/dirname/;
use File::Copy;

sub mkdir_recursive {
    my $path = shift;
    mkdir_recursive(dirname($path)) if not -d dirname($path);
    mkdir $path or die "Could not make dir $path: $!" if not -d $path;
    return;
}

sub mkdir_and_copy {
    my ($from, $to) = @_;
    mkdir_recursive(dirname($to));
    copy($from, $to) or die "Couldn't copy: $!";
    return;
}
Leon Timmermans
Why is this downvoted?
Leon Timmermans
I can't vote, but I guess because you didn't use File::Path::mkpath.
Corion
Since when is that a reason to downvote someone? If it were a core module I would understand (and agree), but that's not the case. Downvoting is for incorrect or stupid solutions, mine is neither.
Leon Timmermans
Beats me. Perhaps because you're hand-rolling directory traversal? Here, have a ++ from me :)
dland
According to corelist File::Path has been part of the core since 5.001.
Michael Carman
Interesting. It's not in 5.10, but it is present in earlier versions.
Leon Timmermans
Corelist is a little buggy about the notation for version numbers. Run "corelist -a File::Path" and you'll see that v2.04 was released with perl "5.01" (instead of 5.010).
Michael Carman
@Leon, I downvoted you because File::Path is a core module and has been for a while (http://perldoc.perl.org/index-modules-F.html) and I felt your solution was unnecessarily re-inventing the wheel. Your solution isn't "bad", just not the the best IMHO, I have taken back my vote.
Robert Gamble
CPAN suggests it isn't in the core, but I guess that's "dual living" confusion, mystery solved.
Leon Timmermans
Maybe because answering your own questions seems like karma whoring, and since you edited the question, somebody thought you were actually asking it?
moritz
I'm the current maintainer of File::Path, it was dual-lifed on CPAN in the run up to 5.10
dland
+18  A: 
use File::Path;
use File::Copy;

my $path = "tardir/dest1/dest2/";
my $file = "test.txt";

if (! -d $path)
{
  mkpath($path) or die "Failed to create $path: $!\n";
}

copy($file,$path) or die "Failed to copy $file: $!\n";
Robert Gamble
File::Path::mkpath throws an exception on error so your "or die" isn't correct.
ysth
+4  A: 

File::Copy::Recursive::fcopy() is non-core but combines the File::Path::mkpath() and File::Copy::copy() solution into something even shorter, and preserves permissions unlike File::Copy. It also contains other nifty utility functions.

runrig
A: 

See the other answers for doing the copying, but for creating the directory Path::Class is very nice to use:

use Path::Class;

my $destination_file  = file('tardir/dest1/dest2/test.txt');
$destination_file->dir->mkpath;

# ... do the copying here
EvdB