Peter
Peter Campbell Smith

Quads and directory enquiries

Weekly challenge 203 — 6 February 2023

Week 203 - 6 Feb 2023

Task 2

Task — Copy folders

We are given paths to two folders, $source and $target, and are asked to write a script that recursively copies the directories in $source to $target, without copying any contained files.

Analysis

Although this seems straightforward, the example leaves a few doubts. Firstly, I have assumed that $target already exists. Secondly, given the example, it's hard to see where recursion comes in as the example simply has 5 directories in $target, none of which has any subdirectories.

My script assumes that $target exists, and my script does recurse. I have illustrated that by adding $target/x/y/2/2m and $target/x/y/2/2n to the example.

I have a sub copy_dirs($source, $target) that creates a like-named directory in $target for any that exist in $source, and if any of these contain subdirectories it recurses with copy_dirs("$source/$subdir", "$target/$subdir").

Note that it would be very easy - one extra line - to copy the contained files as well.

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2023-02-06

use v5.28;
use utf8;
use warnings;
use Time::HiRes qw(time);

# Task: You are given path to two folders, $source and $target. Write a script that recursively copy the directories 
# in $source to $target, without copying any contained files.

# Blog: https://pjcs-pwc.blogspot.com/2023/02/quads-and-directory-enquiries.html

my ($base, $source, $target);

$base = '/home/pi/PWC';
$source = "$base/a/b/c";
$target = "$base/x/y";

copy_dirs($source, $target);

sub copy_dirs {
    
    my ($source, $target, @files, $f);
    ($source, $target) = @_;
    
    # read the contents of $source
    chdir $source;
    opendir(DIR, '.') or die qq[cannot open $source $!];
    @files = readdir DIR;
    closedir DIR;
    
    # if there are dirs other than . and .. created them in target
    for $f (@files) {
        next if $f =~ m|^\.\.?$|;   # ignore . and ..
        next unless -d qq[$source/$f];
        mkdir qq[$target/$f] or die qq[cannot make dir $target/$f $!];
        say qq[created dir $target/$f];
        
        # recurse to create any subfolders
        copy_dirs (qq[$source/$f], qq[$target/$f]);
    }
}