I think the problem is that what you have still reads everything into @subfolders. Here's the snippet I'm talking about.

open(FFINFO,"$folderfolder_file") or die "Can't open $folderfolder_fil+e: $!\n";
# This reads in every line from FFINFO
my @subfolders = <FFINFO>;
my %parents_of;
my $parentid;
# This loop also wants to read every line,
# but the handle is already at EOF,
# so it gets nothing.
while ( my $line = <FFINFO> ) {

If you need @subfolders for some purpose outside the code we're talking about, you could still have it. Just declare my @subfolders; at the same scope as $parentid and %parents_of, without initializing it. Then, right inside the FFINFO read loop, push every $line in. It winds up looking like this:

What this means is, "if @parents is non-empty, return first expression (with nested maps), else return the second expression ($folderid alone in an array reference)." Your description leads me to believe that you have the precedence mixed up. What you describe is this:

Holy smokes! I had to look at this code for about 2 hours to understand it. I see now that build_path always returns a list (array), but usually only with 1 element. I also see that you're using several anonymous arrays for each iteration. It also took me a while to see how you're switching between lists and scalars back and forth. This code is very efficient. It works brilliantly for me now, and I thank you very much for the enlightenment!