About these ads

(Semi-)automatic directory-tree in LaTeX

The dirtree package produces really nice directory trees. The input follows a predefined structure. Manually typing all directories and files in a root directory is painful, even for a relatively short number of items. I wrote a short perl script that outputs the file structure in the right format. It works on Linux and Mac OS X. You need to have a version of Perl installed (and find). The reason, I call this post “semi-auto” is simply because you still have to go to the terminal to run the script, rather than LaTeX does it for you. It is possible to run it from within a tex-document using the “shell-escape” option. However, in my opinion, that is a rather messy solution, which is why I will stick to the “semi-automatic” way here. Still way better than typing…

The dirtree package basically provides a simple command which takes the list of directories and files as argument.

\usepackage{dirtree}
...
\dirtree{%
...
}

The expected directory-tree structure is to be provided in the following format:

.<level><space><text-node>.<space>

Two basic rules are to be respected:

  1. The root always has level 1.
  2. If a node has level n, the next node takes any level between 2 and n+1

Please see the documentation for details on additional customization commands provided by the package such as coloring.

Here is the example given in the documentation:

\documentclass{article}
\usepackage{dirtree}
\begin{document}
\dirtree{%
 .1 /.
 .2 bin.
 .2 home.
 .3 jeancome.
 .4 texmf.
 .5 tex.
 .6 latex.
 .7 dirtree.
 .3 jeancomeson.
 .3 jeancomedaughter.
 .2 usr.
 .3 bin.
 .3 games.
 .4 fortunes.
 .3 include.
 .3 local.
 .4 bin.
 .4 share.
 .5 texmf.
 .6 fonts.
 .6 metapost.
 .6 tex.
 .3 share.
}
\end{document}

 

Semi-automatic dirtree using perl

As promised, here is a little perl script that outputs the directory tree in the form expected by the dirtree package. We use find to go through the tree of directories/files and pipe the output to the script.

#!/usr/bin/perl

while (<STDIN>) {
	my $currLine = $_;
	my $numSlash = @{[$currLine =~ /(\/)/g]};
	my $lastSlash = rindex($currLine, '/');
	my $dirFile = substr($currLine,$lastSlash+1,length($currLine)-$lastSlash-2);
	if ($numSlash == 1) { print ".$numSlash /.\n"; }
	else	{ print ".$numSlash $dirFile.\n"; }
}

Save the code in a perl file, e.g. tree.pl and run:

find root/ | perl tree.pl

in the terminal. The argument to find, here root/, is the directory to start with. It may just be “.” to print the tree of the current directory downwards. Make sure you use the correct path for the perl script. It may be in a different location.

Copy-paste the terminal output into your tex document and typeset it. Here’s what it should look like in the terminal. The result as produced by latex is shown below.

texblog:/ tom$ find . | perl path/to/tree.pl
.1 /. 
.2 bin. 
.3 ls. 
.3 ps. 
.3 pwd. 
.2 etc. 
.2 home. 
.2 usr. 
.3 bin. 
.4 pdf2ps. 
.4 ps2pdf. 
.4 wget. 
.3 local. 
.4 bin. 
.2 var. 
texblog:/ tom$

I’m sure there is a different and/or better way to do the same thing. Possibly with bash only? How about Windows? Please drop me a comment below. Thanks!

Update:

Arjen provided a perl script which does not depend on the external find command and works on different platforms.

#!/usr/bin/perl -w
use strict;
use File::Find;

my $top = shift @ARGV;
die "specify top directory\n" unless defined $top;
chdir $top or die "cannot chdir to $top: $!\n";

find(sub {
    local $_ = $File::Find::name;
    my @F = split '/';
    printf ".%d %s.\n", scalar @F, @F==1 ? $top : $F[-1];
}, '.');

Save the script to a file (e.g. dirtree.pl) and run:

perl dirtree.pl path/to/directory

Thanks Arjen, much appreciated!

About these ads

10 Responses to “(Semi-)automatic directory-tree in LaTeX”

  • notme

    great job! that is what i was looking for!

  • Uwe Ziegenhagen

    For Windows I would recommend some Powershell script. I’ll try to send you something.

    • tom

      That would be awesome. Thanks! Tom.

      • Uwe Ziegenhagen

        The following is the most basic Powershell script I could think of (in a quick & dirty way). If I find some time I will expand it to the level of your script:

        clear-history
        clear-Host
        
        $a = "" + (pwd)
        $a = $a.Replace("\", "/")
        
        "\dirtree{%"
        ".1 " + $a + "."
        
        $folders = gci | ? {$_.PSisContainer}  
        
        foreach ($i in $folders){
             ".2 " +$i.name.Replace("\", "/") +"."
        }
        "}"
      • tom

        Hi Uwe,

        Thanks for taking some time and providing the script above. I really appreciate it!
        I’ll give it a try the next time I get hold of a Windows computer.

        Thanks again!
        Tom.

  • Arjen Bax

    The Perl script below should work on both Unix, Mac and Windows in order to generate the argument to \dirtree. It expects the top directory as argument on the command line; it does not need the external find command.

    #!/usr/bin/perl -w
    use strict;
    use File::Find;
    
    my $top = shift @ARGV;
    die "specify top directory\n" unless defined $top;
    chdir $top or die "cannot chdir to $top: $!\n";
    
    find(sub {
        local $_ = $File::Find::name;
        my @F = split '/';
        printf ".%d %s.\n", scalar @F, @F==1 ? $top : $F[-1];
    }, '.');
    • tom

      Hi Arjen
      Very nice! Thanks a lot for putting this script together.
      Best, Tom.

    • AntonG

      Thanks for the script, it worked great for me under windows. The only problem was underscores in the filenames.
      It would be cool to escape them with backslash right away, so that latex doesn’t throw errors on generated text.

      • tom

        Hi Anton,

        Thanks for your suggestion, I haven’t thought of that. Rather than replacing “_” with “\_” in batch or bash, you could also load the underscore package in the preamble of your document…

        \documentclass{article}
        \usepackage{underscore}
        \begin{document}
        under_score
        \end{document}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 713 other followers

%d bloggers like this: