This is my response to The Weekly Challenge #203.
nums[a] + nums[b] + nums[c] == nums[d]
a < b < c < d
Input: @nums = (1,2,3,6)
Output: 1
Since the only special quadruplets found is
$nums[0] + $nums[1] + $nums[2] == $nums[3].
Example 2:
Input: @nums = (1,1,1,3,5)
Output: 4
$nums[0] + $nums[1] + $nums[2] == $nums[3]
$nums[0] + $nums[1] + $nums[3] == $nums[4]
$nums[0] + $nums[2] + $nums[3] == $nums[4]
$nums[1] + $nums[2] + $nums[3] == $nums[4]
Example 3:
Input: @nums = (3,3,6,4,5)
Output: 0
#! /usr/bin/env raku
unit sub MAIN (*@nums where @nums.elems >= 4 # [1]
&& all(@nums) ~~ /^<[0..9]>*$/, # [1a]
:v(:$verbose));
my @combinations = (^@nums.elems).combinations(4); # [2]
say ": Combinations: { \
@combinations.map({ "(" ~ $_.join(", ") ~ ")" }).join(", ") }"
if $verbose;
my $specials = 0; # [3]
for @combinations -> @candidate # [4]
{
for @candidate.permutations -> ($a, $b, $c, $d) # [5]
{
unless $a < $b < $c < $d # [6]
{
say ": a:$a b:$b c:$c d:$d - Not OK (Rule 2)" if $verbose;
next # [6a]
}
unless @nums[$a] + @nums[$b] + @nums[$c] == @nums[$d] # [7]
{
say ": a:$a b:$b c:$c d:$d - Not OK (Rule 1)" if $verbose;
next; # [7a]
}
$specials++; # [8]
say ": a:$a b:$b c:$c d:$d - OK (Rule 1+2)" if $verbose;
}
}
say $specials; # [9]
[1] We must have at least 4 elements in the array, and I have chosen to restrict them to non-negative integers [1a].
[2] The «a», «b», «c» and «d» values are indices. We use
combinations(4)
to get all possible combinations of 4 of those. (All
the indices are given by ^@nums.elems
). The result is in effect a Set,
so the order is irrelevant (e.g. we get the indices (0,1,2,3)
for the
first example, and only that).
See
docs.raku.org/routine/combinations
for more information about combinations
.
[3] The number of Special Quadruplets; none initially.
[4] Iterate over the combinations (from [2]).
[5] Then we use permutations
to shuffle the
values. (E.g. a shorter (1,2,3)
candidate would give the
(1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1)
permutations)
See
docs.raku.org/routine/permutations for more information about permutations
.
[6] This is the second rule check. Note the chained comparisons. Skip the candidate if it is not met [6a].
[7] This is the first rule check. Skip the candidate if it is not met [7a].
[8] Both rules are met. Increase the count (from [3]).
[9] Print the count.
Running it:
$ ./special-quadruplets 1 2 3 6
1
$ ./special-quadruplets 1 1 1 3 5
4
$ ./special-quadruplets 2 3 6 4 5
0
Looking good.
With verbose mode, and note the first line showing the combinations:
$ ./special-quadruplets -v 1 2 3 6
: Combinations: (0, 1, 2, 3)
: a:0 b:1 c:2 d:3 - OK (Rule 1+2)
: a:0 b:1 c:3 d:2 - Not OK (Rule 2)
: a:0 b:2 c:1 d:3 - Not OK (Rule 2)
: a:0 b:2 c:3 d:1 - Not OK (Rule 2)
: a:0 b:3 c:1 d:2 - Not OK (Rule 2)
: a:0 b:3 c:2 d:1 - Not OK (Rule 2)
: a:1 b:0 c:2 d:3 - Not OK (Rule 2)
: a:1 b:0 c:3 d:2 - Not OK (Rule 2)
: a:1 b:2 c:0 d:3 - Not OK (Rule 2)
: a:1 b:2 c:3 d:0 - Not OK (Rule 2)
: a:1 b:3 c:0 d:2 - Not OK (Rule 2)
: a:1 b:3 c:2 d:0 - Not OK (Rule 2)
: a:2 b:0 c:1 d:3 - Not OK (Rule 2)
: a:2 b:0 c:3 d:1 - Not OK (Rule 2)
: a:2 b:1 c:0 d:3 - Not OK (Rule 2)
: a:2 b:1 c:3 d:0 - Not OK (Rule 2)
: a:2 b:3 c:0 d:1 - Not OK (Rule 2)
: a:2 b:3 c:1 d:0 - Not OK (Rule 2)
: a:3 b:0 c:1 d:2 - Not OK (Rule 2)
: a:3 b:0 c:2 d:1 - Not OK (Rule 2)
: a:3 b:1 c:0 d:2 - Not OK (Rule 2)
: a:3 b:1 c:2 d:0 - Not OK (Rule 2)
: a:3 b:2 c:0 d:1 - Not OK (Rule 2)
: a:3 b:2 c:1 d:0 - Not OK (Rule 2)
1
$ ./special-quadruplets -v 1 1 1 3 5
: Combinations: (0, 1, 2, 3), (0, 1, 2, 4), (0, 1, 3, 4), (0, 2, 3, 4),\
(1, 2, 3, 4)
: a:0 b:1 c:2 d:3 - OK (Rule 1+2)
: a:0 b:1 c:3 d:2 - Not OK (Rule 2)
: a:0 b:2 c:1 d:3 - Not OK (Rule 2)
: a:0 b:2 c:3 d:1 - Not OK (Rule 2)
: a:0 b:3 c:1 d:2 - Not OK (Rule 2)
: a:0 b:3 c:2 d:1 - Not OK (Rule 2)
: a:1 b:0 c:2 d:3 - Not OK (Rule 2)
: a:1 b:0 c:3 d:2 - Not OK (Rule 2)
: a:1 b:2 c:0 d:3 - Not OK (Rule 2)
: a:1 b:2 c:3 d:0 - Not OK (Rule 2)
: a:1 b:3 c:0 d:2 - Not OK (Rule 2)
: a:1 b:3 c:2 d:0 - Not OK (Rule 2)
: a:2 b:0 c:1 d:3 - Not OK (Rule 2)
: a:2 b:0 c:3 d:1 - Not OK (Rule 2)
: a:2 b:1 c:0 d:3 - Not OK (Rule 2)
: a:2 b:1 c:3 d:0 - Not OK (Rule 2)
: a:2 b:3 c:0 d:1 - Not OK (Rule 2)
: a:2 b:3 c:1 d:0 - Not OK (Rule 2)
: a:3 b:0 c:1 d:2 - Not OK (Rule 2)
: a:3 b:0 c:2 d:1 - Not OK (Rule 2)
: a:3 b:1 c:0 d:2 - Not OK (Rule 2)
: a:3 b:1 c:2 d:0 - Not OK (Rule 2)
: a:3 b:2 c:0 d:1 - Not OK (Rule 2)
: a:3 b:2 c:1 d:0 - Not OK (Rule 2)
: a:0 b:1 c:2 d:4 - Not OK (Rule 1)
: a:0 b:1 c:4 d:2 - Not OK (Rule 2)
: a:0 b:2 c:1 d:4 - Not OK (Rule 2)
: a:0 b:2 c:4 d:1 - Not OK (Rule 2)
: a:0 b:4 c:1 d:2 - Not OK (Rule 2)
: a:0 b:4 c:2 d:1 - Not OK (Rule 2)
: a:1 b:0 c:2 d:4 - Not OK (Rule 2)
: a:1 b:0 c:4 d:2 - Not OK (Rule 2)
: a:1 b:2 c:0 d:4 - Not OK (Rule 2)
: a:1 b:2 c:4 d:0 - Not OK (Rule 2)
: a:1 b:4 c:0 d:2 - Not OK (Rule 2)
: a:1 b:4 c:2 d:0 - Not OK (Rule 2)
: a:2 b:0 c:1 d:4 - Not OK (Rule 2)
: a:2 b:0 c:4 d:1 - Not OK (Rule 2)
: a:2 b:1 c:0 d:4 - Not OK (Rule 2)
: a:2 b:1 c:4 d:0 - Not OK (Rule 2)
: a:2 b:4 c:0 d:1 - Not OK (Rule 2)
: a:2 b:4 c:1 d:0 - Not OK (Rule 2)
: a:4 b:0 c:1 d:2 - Not OK (Rule 2)
: a:4 b:0 c:2 d:1 - Not OK (Rule 2)
: a:4 b:1 c:0 d:2 - Not OK (Rule 2)
: a:4 b:1 c:2 d:0 - Not OK (Rule 2)
: a:4 b:2 c:0 d:1 - Not OK (Rule 2)
: a:4 b:2 c:1 d:0 - Not OK (Rule 2)
: a:0 b:1 c:3 d:4 - OK (Rule 1+2)
: a:0 b:1 c:4 d:3 - Not OK (Rule 2)
: a:0 b:3 c:1 d:4 - Not OK (Rule 2)
: a:0 b:3 c:4 d:1 - Not OK (Rule 2)
: a:0 b:4 c:1 d:3 - Not OK (Rule 2)
: a:0 b:4 c:3 d:1 - Not OK (Rule 2)
: a:1 b:0 c:3 d:4 - Not OK (Rule 2)
: a:1 b:0 c:4 d:3 - Not OK (Rule 2)
: a:1 b:3 c:0 d:4 - Not OK (Rule 2)
: a:1 b:3 c:4 d:0 - Not OK (Rule 2)
: a:1 b:4 c:0 d:3 - Not OK (Rule 2)
: a:1 b:4 c:3 d:0 - Not OK (Rule 2)
: a:3 b:0 c:1 d:4 - Not OK (Rule 2)
: a:3 b:0 c:4 d:1 - Not OK (Rule 2)
: a:3 b:1 c:0 d:4 - Not OK (Rule 2)
: a:3 b:1 c:4 d:0 - Not OK (Rule 2)
: a:3 b:4 c:0 d:1 - Not OK (Rule 2)
: a:3 b:4 c:1 d:0 - Not OK (Rule 2)
: a:4 b:0 c:1 d:3 - Not OK (Rule 2)
: a:4 b:0 c:3 d:1 - Not OK (Rule 2)
: a:4 b:1 c:0 d:3 - Not OK (Rule 2)
: a:4 b:1 c:3 d:0 - Not OK (Rule 2)
: a:4 b:3 c:0 d:1 - Not OK (Rule 2)
: a:4 b:3 c:1 d:0 - Not OK (Rule 2)
: a:0 b:2 c:3 d:4 - OK (Rule 1+2)
: a:0 b:2 c:4 d:3 - Not OK (Rule 2)
: a:0 b:3 c:2 d:4 - Not OK (Rule 2)
: a:0 b:3 c:4 d:2 - Not OK (Rule 2)
: a:0 b:4 c:2 d:3 - Not OK (Rule 2)
: a:0 b:4 c:3 d:2 - Not OK (Rule 2)
: a:2 b:0 c:3 d:4 - Not OK (Rule 2)
: a:2 b:0 c:4 d:3 - Not OK (Rule 2)
: a:2 b:3 c:0 d:4 - Not OK (Rule 2)
: a:2 b:3 c:4 d:0 - Not OK (Rule 2)
: a:2 b:4 c:0 d:3 - Not OK (Rule 2)
: a:2 b:4 c:3 d:0 - Not OK (Rule 2)
: a:3 b:0 c:2 d:4 - Not OK (Rule 2)
: a:3 b:0 c:4 d:2 - Not OK (Rule 2)
: a:3 b:2 c:0 d:4 - Not OK (Rule 2)
: a:3 b:2 c:4 d:0 - Not OK (Rule 2)
: a:3 b:4 c:0 d:2 - Not OK (Rule 2)
: a:3 b:4 c:2 d:0 - Not OK (Rule 2)
: a:4 b:0 c:2 d:3 - Not OK (Rule 2)
: a:4 b:0 c:3 d:2 - Not OK (Rule 2)
: a:4 b:2 c:0 d:3 - Not OK (Rule 2)
: a:4 b:2 c:3 d:0 - Not OK (Rule 2)
: a:4 b:3 c:0 d:2 - Not OK (Rule 2)
: a:4 b:3 c:2 d:0 - Not OK (Rule 2)
: a:1 b:2 c:3 d:4 - OK (Rule 1+2)
: a:1 b:2 c:4 d:3 - Not OK (Rule 2)
: a:1 b:3 c:2 d:4 - Not OK (Rule 2)
: a:1 b:3 c:4 d:2 - Not OK (Rule 2)
: a:1 b:4 c:2 d:3 - Not OK (Rule 2)
: a:1 b:4 c:3 d:2 - Not OK (Rule 2)
: a:2 b:1 c:3 d:4 - Not OK (Rule 2)
: a:2 b:1 c:4 d:3 - Not OK (Rule 2)
: a:2 b:3 c:1 d:4 - Not OK (Rule 2)
: a:2 b:3 c:4 d:1 - Not OK (Rule 2)
: a:2 b:4 c:1 d:3 - Not OK (Rule 2)
: a:2 b:4 c:3 d:1 - Not OK (Rule 2)
: a:3 b:1 c:2 d:4 - Not OK (Rule 2)
: a:3 b:1 c:4 d:2 - Not OK (Rule 2)
: a:3 b:2 c:1 d:4 - Not OK (Rule 2)
: a:3 b:2 c:4 d:1 - Not OK (Rule 2)
: a:3 b:4 c:1 d:2 - Not OK (Rule 2)
: a:3 b:4 c:2 d:1 - Not OK (Rule 2)
: a:4 b:1 c:2 d:3 - Not OK (Rule 2)
: a:4 b:1 c:3 d:2 - Not OK (Rule 2)
: a:4 b:2 c:1 d:3 - Not OK (Rule 2)
: a:4 b:2 c:3 d:1 - Not OK (Rule 2)
: a:4 b:3 c:1 d:2 - Not OK (Rule 2)
: a:4 b:3 c:2 d:1 - Not OK (Rule 2)
4
$ ./special-quadruplets -v 2 3 6 4 5
: Combinations: (0, 1, 2, 3), (0, 1, 2, 4), (0, 1, 3, 4), (0, 2, 3, 4), \
(1, 2, 3, 4)
: a:0 b:1 c:2 d:3 - Not OK (Rule 1)
: a:0 b:1 c:3 d:2 - Not OK (Rule 2)
: a:0 b:2 c:1 d:3 - Not OK (Rule 2)
: a:0 b:2 c:3 d:1 - Not OK (Rule 2)
: a:0 b:3 c:1 d:2 - Not OK (Rule 2)
: a:0 b:3 c:2 d:1 - Not OK (Rule 2)
: a:1 b:0 c:2 d:3 - Not OK (Rule 2)
: a:1 b:0 c:3 d:2 - Not OK (Rule 2)
: a:1 b:2 c:0 d:3 - Not OK (Rule 2)
: a:1 b:2 c:3 d:0 - Not OK (Rule 2)
: a:1 b:3 c:0 d:2 - Not OK (Rule 2)
: a:1 b:3 c:2 d:0 - Not OK (Rule 2)
: a:2 b:0 c:1 d:3 - Not OK (Rule 2)
: a:2 b:0 c:3 d:1 - Not OK (Rule 2)
: a:2 b:1 c:0 d:3 - Not OK (Rule 2)
: a:2 b:1 c:3 d:0 - Not OK (Rule 2)
: a:2 b:3 c:0 d:1 - Not OK (Rule 2)
: a:2 b:3 c:1 d:0 - Not OK (Rule 2)
: a:3 b:0 c:1 d:2 - Not OK (Rule 2)
: a:3 b:0 c:2 d:1 - Not OK (Rule 2)
: a:3 b:1 c:0 d:2 - Not OK (Rule 2)
: a:3 b:1 c:2 d:0 - Not OK (Rule 2)
: a:3 b:2 c:0 d:1 - Not OK (Rule 2)
: a:3 b:2 c:1 d:0 - Not OK (Rule 2)
: a:0 b:1 c:2 d:4 - Not OK (Rule 1)
: a:0 b:1 c:4 d:2 - Not OK (Rule 2)
: a:0 b:2 c:1 d:4 - Not OK (Rule 2)
: a:0 b:2 c:4 d:1 - Not OK (Rule 2)
: a:0 b:4 c:1 d:2 - Not OK (Rule 2)
: a:0 b:4 c:2 d:1 - Not OK (Rule 2)
: a:1 b:0 c:2 d:4 - Not OK (Rule 2)
: a:1 b:0 c:4 d:2 - Not OK (Rule 2)
: a:1 b:2 c:0 d:4 - Not OK (Rule 2)
: a:1 b:2 c:4 d:0 - Not OK (Rule 2)
: a:1 b:4 c:0 d:2 - Not OK (Rule 2)
: a:1 b:4 c:2 d:0 - Not OK (Rule 2)
: a:2 b:0 c:1 d:4 - Not OK (Rule 2)
: a:2 b:0 c:4 d:1 - Not OK (Rule 2)
: a:2 b:1 c:0 d:4 - Not OK (Rule 2)
: a:2 b:1 c:4 d:0 - Not OK (Rule 2)
: a:2 b:4 c:0 d:1 - Not OK (Rule 2)
: a:2 b:4 c:1 d:0 - Not OK (Rule 2)
: a:4 b:0 c:1 d:2 - Not OK (Rule 2)
: a:4 b:0 c:2 d:1 - Not OK (Rule 2)
: a:4 b:1 c:0 d:2 - Not OK (Rule 2)
: a:4 b:1 c:2 d:0 - Not OK (Rule 2)
: a:4 b:2 c:0 d:1 - Not OK (Rule 2)
: a:4 b:2 c:1 d:0 - Not OK (Rule 2)
: a:0 b:1 c:3 d:4 - Not OK (Rule 1)
: a:0 b:1 c:4 d:3 - Not OK (Rule 2)
: a:0 b:3 c:1 d:4 - Not OK (Rule 2)
: a:0 b:3 c:4 d:1 - Not OK (Rule 2)
: a:0 b:4 c:1 d:3 - Not OK (Rule 2)
: a:0 b:4 c:3 d:1 - Not OK (Rule 2)
: a:1 b:0 c:3 d:4 - Not OK (Rule 2)
: a:1 b:0 c:4 d:3 - Not OK (Rule 2)
: a:1 b:3 c:0 d:4 - Not OK (Rule 2)
: a:1 b:3 c:4 d:0 - Not OK (Rule 2)
: a:1 b:4 c:0 d:3 - Not OK (Rule 2)
: a:1 b:4 c:3 d:0 - Not OK (Rule 2)
: a:3 b:0 c:1 d:4 - Not OK (Rule 2)
: a:3 b:0 c:4 d:1 - Not OK (Rule 2)
: a:3 b:1 c:0 d:4 - Not OK (Rule 2)
: a:3 b:1 c:4 d:0 - Not OK (Rule 2)
: a:3 b:4 c:0 d:1 - Not OK (Rule 2)
: a:3 b:4 c:1 d:0 - Not OK (Rule 2)
: a:4 b:0 c:1 d:3 - Not OK (Rule 2)
: a:4 b:0 c:3 d:1 - Not OK (Rule 2)
: a:4 b:1 c:0 d:3 - Not OK (Rule 2)
: a:4 b:1 c:3 d:0 - Not OK (Rule 2)
: a:4 b:3 c:0 d:1 - Not OK (Rule 2)
: a:4 b:3 c:1 d:0 - Not OK (Rule 2)
: a:0 b:2 c:3 d:4 - Not OK (Rule 1)
: a:0 b:2 c:4 d:3 - Not OK (Rule 2)
: a:0 b:3 c:2 d:4 - Not OK (Rule 2)
: a:0 b:3 c:4 d:2 - Not OK (Rule 2)
: a:0 b:4 c:2 d:3 - Not OK (Rule 2)
: a:0 b:4 c:3 d:2 - Not OK (Rule 2)
: a:2 b:0 c:3 d:4 - Not OK (Rule 2)
: a:2 b:0 c:4 d:3 - Not OK (Rule 2)
: a:2 b:3 c:0 d:4 - Not OK (Rule 2)
: a:2 b:3 c:4 d:0 - Not OK (Rule 2)
: a:2 b:4 c:0 d:3 - Not OK (Rule 2)
: a:2 b:4 c:3 d:0 - Not OK (Rule 2)
: a:3 b:0 c:2 d:4 - Not OK (Rule 2)
: a:3 b:0 c:4 d:2 - Not OK (Rule 2)
: a:3 b:2 c:0 d:4 - Not OK (Rule 2)
: a:3 b:2 c:4 d:0 - Not OK (Rule 2)
: a:3 b:4 c:0 d:2 - Not OK (Rule 2)
: a:3 b:4 c:2 d:0 - Not OK (Rule 2)
: a:4 b:0 c:2 d:3 - Not OK (Rule 2)
: a:4 b:0 c:3 d:2 - Not OK (Rule 2)
: a:4 b:2 c:0 d:3 - Not OK (Rule 2)
: a:4 b:2 c:3 d:0 - Not OK (Rule 2)
: a:4 b:3 c:0 d:2 - Not OK (Rule 2)
: a:4 b:3 c:2 d:0 - Not OK (Rule 2)
: a:1 b:2 c:3 d:4 - Not OK (Rule 1)
: a:1 b:2 c:4 d:3 - Not OK (Rule 2)
: a:1 b:3 c:2 d:4 - Not OK (Rule 2)
: a:1 b:3 c:4 d:2 - Not OK (Rule 2)
: a:1 b:4 c:2 d:3 - Not OK (Rule 2)
: a:1 b:4 c:3 d:2 - Not OK (Rule 2)
: a:2 b:1 c:3 d:4 - Not OK (Rule 2)
: a:2 b:1 c:4 d:3 - Not OK (Rule 2)
: a:2 b:3 c:1 d:4 - Not OK (Rule 2)
: a:2 b:3 c:4 d:1 - Not OK (Rule 2)
: a:2 b:4 c:1 d:3 - Not OK (Rule 2)
: a:2 b:4 c:3 d:1 - Not OK (Rule 2)
: a:3 b:1 c:2 d:4 - Not OK (Rule 2)
: a:3 b:1 c:4 d:2 - Not OK (Rule 2)
: a:3 b:2 c:1 d:4 - Not OK (Rule 2)
: a:3 b:2 c:4 d:1 - Not OK (Rule 2)
: a:3 b:4 c:1 d:2 - Not OK (Rule 2)
: a:3 b:4 c:2 d:1 - Not OK (Rule 2)
: a:4 b:1 c:2 d:3 - Not OK (Rule 2)
: a:4 b:1 c:3 d:2 - Not OK (Rule 2)
: a:4 b:2 c:1 d:3 - Not OK (Rule 2)
: a:4 b:2 c:3 d:1 - Not OK (Rule 2)
: a:4 b:3 c:1 d:2 - Not OK (Rule 2)
: a:4 b:3 c:2 d:1 - Not OK (Rule 2)
0
$source
and $target
.
$source
to
$target
except any files.
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 terms «directory» and «folder» are generally synonymous, but I will stick to the former.
My program messes with the notion of the
current directory, so I have decided to require absolute paths on the $source
and $target
. The example does so, so it is probably reasonable to do so.
/a/b
is not a path
that I would like to see on my pc, so I have decided to prefix it (and the target
/x/y
) with /tmp
.
Use the following shell script to set up the directories and files:
File: setup.sh
#! /usr/bin/env sh
rm -R /tmp/x
rm -R /tmp/a
mkdir /tmp/x
mkdir /tmp/x/y
mkdir /tmp/a /tmp/a/b /tmp/a/b/c
mkdir /tmp/a/b/c/1 /tmp/a/b/c/2 /tmp/a/b/c/3 /tmp/a/b/c/4 /tmp/a/b/c/5
touch /tmp/a/b/c/1/1.txt
touch /tmp/a/b/c/2/2.txt
touch /tmp/a/b/c/3/3.txt
touch /tmp/a/b/c/5/5.txt
Then the surprisingly short program:
File: copy-directory
#! /usr/bin/env raku
unit sub MAIN ($source where $source.substr(0,1) eq '/' # [1]
&& $source.IO.e && $source.IO.d = '/tmp/a/b/c',
$target where $target.substr(0,1) eq '/' # [2]
&& $target.IO.e && $target.IO.d = '/tmp/x/y',
:d(:$dryrun), # [3]
:v(:$verbose) = $dryrun);
indir($source, { do-dir(".") }); # [4]
sub do-dir ($dir) # [5]
{
for dir($dir).sort -> $file # [6]
{
next unless $file.d; # [7]
say ": mkdir $target/$file { $dryrun ?? ' [Dryrun]' !! '' }" if $verbose;
mkdir "$target/$file" unless $dryrun && "$target/$file".IO.e; # [8]
do-dir($file); # [9]
}
}
[1]
The source directory (with path). The first chracter must be «/»
(the substr
part), the directory must exist (IO.e
) and
it must be a directory (IO.d
). Note the default value at the end.
See docs.raku.org/routine/e and docs.raku.org/routine/d for more information about those file tests.
[2] The target directory (with path).
[3] Use the «--dryrun» (or «-d») option to omit the creation of the directories. It is only useful when combined with «--verbose» (or «-v»), so the latter is enabled by default by dryrun.
[4] This recursive call starts the show. The indir
call executes the given code block (the second argument), with the current
directory set to the first argument inside that block only. The
resursive procedure starts off in the source directory, which we then specify
as «.» in the call.
See
docs.raku.org/routine/indir for
more information about indir
.
[5] The recursive procedure. The argument is the directory to inspect. It is specified relative to the source directory.
[6] Get the content of the directory (with dir
), and
iterate over them. Sorted, so that we get the same order each time.
See
docs.raku.org/routine/dir for more information about dir
[7] Skip non-directories. (Note that Raku does not give you «.» and «..», so we do not have to handle them.)
[8] Create the directory in the target location, unless it exists already.
[9] Recursively follow the directory.
Running it, with verbose mode to show what is going on:
$ ./copy-directory -v
: mkdir /tmp/x/y/1
: mkdir /tmp/x/y/2
: mkdir /tmp/x/y/3
: mkdir /tmp/x/y/4
: mkdir /tmp/x/y/5
Looking good.
Let us check that it works recursively:
$ ./setup.sh
$ ./copy-directory -d /tmp/a /tmp/x/y
: mkdir /tmp/x/y/b [Dryrun]
: mkdir /tmp/x/y/b/c [Dryrun]
: mkdir /tmp/x/y/b/c/1 [Dryrun]
: mkdir /tmp/x/y/b/c/2 [Dryrun]
: mkdir /tmp/x/y/b/c/3 [Dryrun]
: mkdir /tmp/x/y/b/c/4 [Dryrun]
: mkdir /tmp/x/y/b/c/5 [Dryrun]
Looking good.
And that's it.