Peter’s blog ✴ Week 203 ✴ 6 February 2023
THE WEEKLY CHALLENGE
Quads and directory enquiries
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.
Example 1
Input: = '/a/b/c' and = '/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
My script assumes that $source and $target exist - I have created them in the preamble -
and my script recurses.
My sub copy_dirs($source, $target) creates a like-named sub-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").
It would be very easy - one extra line - to copy the contained files as well.
Practical discussion around the task makes it easy to follow the solution. Well done.
#!/usr/bin/perl # Peter Campbell Smith - 2023-02-06, revised 2024-11-14, 2026-06-17 use v5.28; use utf8; use warnings; # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge # clear out previous runs system 'rm -r /tmp/from' if -e '/tmp/from'; system 'rm -r /tmp/to' if -e '/tmp/to'; # create roots of from and to mkdir '/tmp/from'; mkdir '/tmp/to'; # create 'from' structure chdir '/tmp/from'; mkdir 'apple'; mkdir 'banana'; mkdir 'banana/cherry'; mkdir 'banana/cherry/date'; mkdir 'banana/cherry/orange'; mkdir 'banana/pear'; # now do what was asked my ($input, $output); copy_dirs('/tmp/from', '/tmp/to', ''); say qq[\nInput:\n$input\nOutput:\n$output]; sub copy_dirs { my ($source, $target, @files, $f, $dashes); ($source, $target, $dashes) = @_; # read the contents of $source chdir $source; opendir(DIR, '.') or die qq[cannot open $source $!]; @files = sort readdir DIR; closedir DIR; # if there are dirs other than . and .. create them in target for $f (@files) { next if $f =~ m|^\.\.?$|; # ignore . and .. $input .= qq[$dashes$f\n]; next unless -d qq[$source/$f]; mkdir qq[$target/$f] or die qq[cannot make dir $target/$f $!]; $output .= qq[$dashes$f\n]; # recurse to create any subfolders copy_dirs (qq[$source/$f], qq[$target/$f], $dashes . '--'); } }
14 lines of code
Input: apple banana --cherry ----date ----orange --pear Output: apple banana --cherry ----date ----orange --pear
Any content of this website which has been created by Peter Campbell Smith is in the public domain