convert a `find` like output to a `tree` like output

In my Debian 10 I have tree v1.8.0. It supports --fromfile.

--fromfile
Reads a directory listing from a file rather than the file-system. Paths provided on the command line are files to read from rather than directories to search. The dot (.) directory indicates that tree should read paths from standard input.

This way I can feed tree with output from find:

find /foo | tree -d --fromfile .

Problems:

  • If tree reads /foo/whatever or foo/whatever then foo will be reported as a subdirectory of .. Similarly with ./whatever: . will be reported as an additional level named . under the top level .. So the results may not entirely meet your formal expectations, there will always be a top level . entry. It will be there even if find finds nothing or throws an error.

  • Filenames with newlines will confuse tree. Using find -print0 is not an option because there is no corresponding switch for tree.


So, I finally wrote what I hope will become the python tree utils. Find it at http://pytree.org


I whipped up a Perl script that splits the paths (on "/"), creates a hash tree, and then prints the tree with Data::TreeDumper. Kinda hacky, but it works:

#!/usr/bin/perl
use strict;
use warnings;

use Data::TreeDumper;

my %tree;
while (<>) {
    my $t = \%tree;
    foreach my $part (split m!/!, $_) {
        next if $part eq '';
        chomp $part;
        $t->{$part} ||= {};
        $t = $t->{$part};
    }
}
sub check_tree {
    my $t = shift;
    foreach my $hash (values %$t) {
        undef $hash unless keys %$hash;
        check_tree($hash);
    }    
}
check_tree(\%tree);
my $output = DumpTree(\%tree);
$output =~ s/ = undef.*//g;
$output =~ s/ \[H\d+\].*//g;
print $output;

Here's the output:

$ perl test.pl test.data

|- fruit 
|  |- apple 
|  |  |- green
|  |  |- red
|  |  `- yellow
|  |- banana 
|  |  |- green
|  |  `- yellow
|  `- orange 
|     |- green
|     `- orange
|- i_want_my_mommy
`- person 
   |- men 
   |  |- bob
   |  `- david
   `- women 
      `- eve