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 thattree
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
orfoo/whatever
thenfoo
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 iffind
finds nothing or throws an error.Filenames with newlines will confuse
tree
. Usingfind -print0
is not an option because there is no corresponding switch fortree
.
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