ETOOBUSY π minimal blogging for the impatient
PWC203 - Copy Directory
TL;DR
On with TASK #2 from The Weekly Challenge #203. Enjoy!
The challenge
You are given path to two folders,
$source
and$target
.Write a script that recursively copy the directory from
$source
to$target
except any files.Example
Input: $source = '/a/b/c' and $target = '/x/y' Source directory structure: βββ a β βββ b β βββ c β βββ 1 β β βββ 1.txt β βββ 2 β β βββ 2.txt β βββ 3 β β βββ 3.txt β βββ 4 β βββ 5 β βββ 5.txt Target directory structure: βββ x β βββ y Expected Result: βββ x β βββ y | βββ 1 β βββ 2 β βββ 3 β βββ 4 β βββ 5
The questions
Uhβ¦ messing up with the filesystem is wicked without proper requirements! Likeβ¦
- β¦ what happens if some items are already there
- β¦ what permissions should be set on the newly created directories?
- β¦ should we try to set ownership too?
The solution
I decided to go for CORE stuffβ¦ so thereβs some work to do:
#!/usr/bin/env perl
use v5.24;
use warnings;
use English '-no_match_vars';
use experimental 'signatures';
no warnings 'experimental::signatures';
use File::Spec::Functions qw< splitpath splitdir catdir catpath >;
use File::Path qw< make_path >;
copy_directory(@ARGV);
sub copy_directory ($from, $to) {
my ($fv, $fds) = splitpath($from, 'no-file');
my ($tv, $tds) = splitpath($to, 'no-file');
opendir my $dh, $from or die "opendir('$from'): $OS_ERROR";
for my $item (readdir($dh)) {
next if ($item eq '.') || ($item eq '..');
my $source = catpath($fv, $fds, $item);
next unless -d $source;
my (undef, undef, $mode) = stat($source);
my $target = catpath($tv, $tds, $item);
make_path($target, {mode => $mode});
__SUB__->($source, $target);
}
}
Raku allows for some more idiomatic stuff:
#!/usr/bin/env raku
use v6;
sub MAIN ($from, $to) { copy-directory($from, $to) }
sub copy-directory (IO::Path() $from, IO::Path() $to) {
for $from.dir -> $source {
next unless $source.d;
my $target = $to.child($source.basename).mkdir($source.mode);
samewith($source, $target);
}
}
Aaaaaaaaandβ¦ thatβs all folks!