use strict; use warnings; my %folders; my $parentId; while () { chomp; if (m/^Folder\s+(\d+)\s*-\s*(.*)\.$/) { # new folder my ($folderId, $folderName) = ($1, $2); die "Duplicate entry for $folderId ($folderName) at line $.\n" if ++$folders{$folderId}{idCount} > 1; # Create the new folder $folders{$folderId}{folders} = []; $folders{$folderId}{name} = $folderName; $parentId = $folderId; } elsif (m/^\s+subfolder (\d+)\.$/) { # New subfolder my $folderId = $1; die "No parent folder for $folderId. Data format error at line $.\n" if ! defined $parentId; warn "Probably bad data. Subfolder $folderId has already been seen\n" if exists $folders{$folderId}; push @{$folders{$parentId}{folders}}, $folderId; $folders{$folderId}{hasParent} = 1; } else { # Bogus line } } genPath ($_) for sort grep {! $folders{$_}{hasParent}} keys %folders; sub genPath { my ($folderId, $root) = @_; $root .= '/'; die "Missing folder information for $folderId\n" if ! exists $folders{$folderId}{name}; die "Cycle in 'tree' involving $folderId and path $root\n" if ++$folders{$folderId}{visits} > 1; $root .= $folders{$folderId}{name}; print "$root\n"; genPath ($_, $root) for @{$folders{$folderId}{folders}}; } __DATA__ Folder 1298 - foldername_ten. subfolder 1299. subfolder 1300. Folder 1299 - foldername_eleven. No sub folders. Folder 1300 - foldername_twelve. No sub folders. Folder 1311 - foldername_thirteen. subfolder 1317. subfolder 1318. Folder 1317 - foldername_twelve. No sub folders. Folder 1318 - foldername_twelve. No sub folders. #### /foldername_ten /foldername_ten/foldername_eleven /foldername_ten/foldername_twelve /foldername_thirteen /foldername_thirteen/foldername_twelve /foldername_thirteen/foldername_twelve