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, revised 2024-11-14

use v5.28;
use utf8;
use warnings;

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

system 'rm -r /tmp/from' if -e '/tmp/from';
system 'rm -r /tmp/to' if -e '/tmp/to';

mkdir '/tmp/from';
chdir '/tmp/from';
mkdir 'a';
mkdir 'b';
mkdir 'b/c';
mkdir '/tmp/to';

copy_dirs('/tmp/from', '/tmp/to');

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 ..
        print qq[found dir $source/$f ...];
        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]);
    }
}

Output

found dir /tmp/from/b ... created dir /tmp/to/b
found dir /tmp/from/b/c ... created dir /tmp/to/b/c
found dir /tmp/from/a ... created dir /tmp/to/a

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain