perl1234 has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks,

I am interested in developing a small tool which reads in a file (generated using the "tree" function in Unix) that has the paths to all files in a folder (and subfolders).

There are examples in Tk which generates a windows-y type explorer view from a hash reference.

I am struggling generating this complex hash in a hash which traverses according to the directory structure.

Any help (hints) will be greatly appreciated.

Many thanks for this resource.

Best wishes,

Anuj

Replies are listed 'Best First'.
Re: file explorer type window
by pme (Monsignor) on Aug 17, 2015 at 11:03 UTC

      Thank you. I have already looked at both the links. I found a code from http://www.rtapo.com/tutorials/tk_tree.html

      Code: http://www.rtapo.com/downloads/tk_tree_ex_1.pl.txt

      You can see that they are using a hash of hash to build a "job" structure and then display it graphically.

      If only I could read a file with similar sturcture and display it?!

Re: file explorer type window
by RichardK (Parson) on Aug 17, 2015 at 11:14 UTC

    The version of tree on my Linux system can output JSON or XML, which are much easier to work with than the standard text output.

    You can then directly convert JSON to a perl structure, see JSON

      Thank you. I am not familiar with JSON. I dont think my version of "tree" can export in XML or JSON.
Re: file explorer type window
by Anonymous Monk on Aug 17, 2015 at 17:00 UTC

    Here's code running against a subtree from my system where I stuffed the tree output into a DATA section just to make a self-contained test case. I find it easier to read the YAML output than the Data::Dump output.

    #!/usr/bin/perl # http://perlmonks.org/?node_id=1138867 use strict; use warnings; my @depth = {}; while(<DATA>) { /\S/ or last; /([| ]*?[|`]-- )?(.*)/ or next; my $level = length($1 // 0) / 4; $depth[$level]{$2} = $depth[$level + 1] = {}; } use YAML; print Dump $depth[0]; #use Data::Dump qw(pp); pp $depth[0]; __DATA__ wiki |-- RicksWiki_3_3 | |-- RCS | | |-- README,v | | |-- fast,v | | `-- go,v | |-- README | |-- cgi-bin | | |-- RCS | | | |-- server.pl,v | | | `-- wiki.pl,v | | |-- server.pl | | `-- wiki.pl | |-- doc | | |-- RCS | | | `-- index.html,v | | `-- index.html | |-- fast | |-- go | |-- history | | |-- CodeNotes,v | | |-- FormattingRules,v | | `-- PlayGround,v | |-- log.wiki | `-- pages | |-- CamelCase | |-- CodeNotes | |-- FormattingComments | |-- FormattingRules | |-- InstallInstructions | |-- MainPage | |-- OneMinuteWiki | |-- PlayGround | |-- RicksWikiFeatures | `-- SeedPage `-- RicksWiki_3_3.tgz 8 directories, 27 files

    And here's the output:

    --- wiki: RicksWiki_3_3: RCS: 'README,v': {} 'fast,v': {} 'go,v': {} README: {} cgi-bin: RCS: 'server.pl,v': {} 'wiki.pl,v': {} server.pl: {} wiki.pl: {} doc: RCS: 'index.html,v': {} index.html: {} fast: {} go: {} history: 'CodeNotes,v': {} 'FormattingRules,v': {} 'PlayGround,v': {} log.wiki: {} pages: CamelCase: {} CodeNotes: {} FormattingComments: {} FormattingRules: {} InstallInstructions: {} MainPage: {} OneMinuteWiki: {} PlayGround: {} RicksWikiFeatures: {} SeedPage: {} RicksWiki_3_3.tgz: {}

    Note that "tree" in its basic form does not indicate whether a name is a file or a directory.

      Oops on the level line, (though it still works :)

      my $level = length($1 // '') / 4;

        Dear All,

        Many thanks for your perls of wisdom.

        Here is a crude prototype of what I am interested in.

        #!/usr/bin/perl # http://perlmonks.org/?node_id=1138867 use strict; use warnings; use Tk::ObjScanner; my @depth = {}; open (DATA, "data.txt");#same as what was in the example above while(<DATA>) { /\S/ or last; chomp $_; /([\| ]*?[\|`]-- )?(.*)/ or next; my $a=$1; my $b=$2; if (!defined($a)){ $a=""; } if (!defined($b)){ $b=""; } my $y=length($a); my $level = $y/4; $depth[$level]{$2} = $depth[$level + 1] = {}; } #use YAML; print Dump $depth[0]; close DATA; MainWindow->new->ObjScanner(caller => $depth[0])->pack; + Tk::MainLoop;