+sub build {
+ my ($tree, $prefix) = @_;
+ my @ret;
+ my $r = delete $tree->{_};
+ while (my ($d, $v) = each %$tree) {
+ if (ref $v) {
+ my $dir = catdir $prefix, $d;
+ mkdir $dir or die "mkdir($dir): $!";
+ my @r = build($v, $dir);
+ push @ret, map [
+ $_->[0],
+ ref eq 'main' ? @{$_}[1 .. 3]
+ : map { catdir($d, $_) } @{$_}[1 .. 3]
+ ], @r unless $r;
+ } else {
+ my $file = catfile($prefix, $d);
+ open my $fh, '>', $file or die "open($file): $!";
+ print $fh $v;
+ close $fh;
+ }
+ }
+ return $r ? bless $r, 'main' : @ret;
+}