by Arne Sommer

[223] Published 11. February 2023.

This is my response to The Weekly Challenge #203.

You are given an array of integers.

Write a script to find out the total special quadruplets for the given array.

Special Quadruplets are such that satisfies the following 2 rules.
1. `nums[a] + nums[b] + nums[c] == nums[d]`
2. `a < b < c < d`
Example 1: ```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 ```
File: special-quadruplets ```#! /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 ```

## Challenge #203.2: Copy Directory

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 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.

[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.

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.