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

余生长醉 提交于 2019-12-23 15:23:11

问题


This question is a generalized version of the Output of ZipArchive() in tree format question.


Just before I am wasting time on writing this (*nix command line) utility, it will be a good idea to find out if someone already wrote it. I would like a utility that will get as its' standard input a list such as the one returned by find(1) and will output something similar to the one by tree(1)

E.g.:

Input:

/fruit/apple/green
/fruit/apple/red
/fruit/apple/yellow
/fruit/banana/green
/fruit/banana/yellow
/fruit/orange/green
/fruit/orange/orange
/i_want_my_mommy
/person/men/bob
/person/men/david
/person/women/eve

Output

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

Usage should be something like:

list2tree --delimiter="/" < Input > Output

Edit0: It seems that I was not clear about the purpose of this exercise. I like the output of tree, but I want it for arbitrary input. It might not be part of any file system name-space.

Edit1: Fixed person branch on the output. Thanks, @Alnitak.


回答1:


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



回答2:


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




回答3:


I would simply use tree myself but here's a simple thing that I wrote a few days ago that prints a tree of a directory. It doesn't expect input from find (which makes is different from your requirements) and doesn't do the |- display (which can be done with some small modifications). You have to call it like so tree <base_path> <initial_indent>. intial_indent is the number of characters the first "column" is indented.

function tree() {
    local root=$1
    local indent=$2
    cd $root
    for i in *
    do
    for j in $(seq 0 $indent)
    do 
        echo -n " "
    done
    if [ -d $i ]
    then
        echo "$i/"
        (tree $i $(expr $indent + 5))
    else
        echo $i
    fi
    done
}



回答4:


An other tool is treeify written in Rust.

Assuming you have Rust installed get it with:

$ cargo install treeify


来源:https://stackoverflow.com/questions/4420878/convert-a-find-like-output-to-a-tree-like-output

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!