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

34,648

Solution 1

use File::Path;
use File::Copy;

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

if (! -d $path)
{
  my $dirs = eval { mkpath($path) };
  die "Failed to create $path: $@\n" unless $dirs;
}

copy($file,$path) or die "Failed to copy $file: $!\n";

Solution 2

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;
}

Solution 3

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.

Solution 4

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
Share:
34,648
Chandrasekhar
Author by

Chandrasekhar

Updated on January 09, 2020

Comments

  • Chandrasekhar
    Chandrasekhar over 4 years

    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");
    

    won't work since the directory tardir/dest1/dest2 does not yet exist. What is the best way to copy with directory creation in Perl?

  • Michael Carman
    Michael Carman over 15 years
    According to corelist File::Path has been part of the core since 5.001.
  • Leon Timmermans
    Leon Timmermans over 15 years
    Interesting. It's not in 5.10, but it is present in earlier versions.
  • Michael Carman
    Michael Carman over 15 years
    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).
  • user2522201
    user2522201 over 15 years
    @Leon, I downvoted you because File::Path is a core module and has been for a while (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.
  • Leon Timmermans
    Leon Timmermans over 15 years
    CPAN suggests it isn't in the core, but I guess that's "dual living" confusion, mystery solved.
  • dland
    dland over 15 years
    I'm the current maintainer of File::Path, it was dual-lifed on CPAN in the run up to 5.10
  • ysth
    ysth over 15 years
    File::Path::mkpath throws an exception on error so your "or die" isn't correct.
  • Marco
    Marco over 12 years
    This approached proved to be the easiest of the choices available. I opted to use File::Copy::Recursive's dircopy function. The 2 main advantages are that File::Copy::Recursive's functions will automatically make any dir. structure and also will preserve the permissions when it makes copies.