Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Good day everyone -

Is there a fast and efficient way to draw directory tree structures (aka depth-indented listings) like the unix's tree command, that is, is there a way to draw the following using TikZ?

root
  |
  |--- dir1
  |     |
  |     |-- a1
  |     |-- a2
  |--- dir2
  |--- dir3

I've checked tikz-tree and tikz-qtree, but the packages always want to grow the tree balanced and not down then to the right.

Any advice is truly appreciated.

Thanks.

share|improve this question
2  
If TikZ is not really obligatory, then try dirtree package. –  przemoc Jul 20 '11 at 22:38
    
Using TikZ is tricky here: you can get part of the way by using grow with three children = one child at (2em,-2em) and two children at (2em,-2em) and (2em, -4em) and edge from parent to draw perpendicular lines. But as the manual says, tree layout occurs without reasoning about the size of the children. tikz-qtree handles reasoning about the size of the children, and the grow'=right option will grow trees rightwards, but balanced instead of bottom-heavy. So some variant of tikz-qtree's code should work...but I don't understand its code well enough to write that variant. –  Ben Lerner Jul 21 '11 at 0:53
add comment

2 Answers

Here are two concepts doing it with TikZ. The first one doesn't draw enough lines, the second one draws too many. I guess one needs counters for each level. Those counters would be increased if the same level occurs again and draw a line to it, while they would reset when a higher level is encounterd, e.g. like one could principally do with

\usepackage{chngcntr}
\counterwithin{leveltwo}{levelone}

Probably I'll get to it this week, but don't count on it. Here's what I have so far:

\documentclass[parskip,14pt]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}

\newcounter{treeline}

\newcommand{\treeroot}[1]{% Title
\node[above] at (0,0) {#1};%
\setcounter{treeline}{0}
}

\newcommand{\treeentry}[2]{% Title, Level
\draw[->] (#2-1,-\value{treeline}/2) -- (#2-1,-\value{treeline}/2-0.5) -- (#2+0.5,-\value{treeline}/2-0.5) node[right] {#1};
\stepcounter{treeline}
}

\newcommand{\altentry}[2]{% Title, Level
\draw[->] (#2-1,-\value{treeline}/2) -- (#2-1,-\value{treeline}/2-0.5) -- (#2+0.5,-\value{treeline}/2-0.5) node[right] {#1};
\foreach \x in {1,...,#2}
{   \draw (\x-1,-\value{treeline}/2) -- (\x-1,-\value{treeline}/2-0.5);
}
\stepcounter{treeline}
}

\begin{document}

\begin{tikzpicture}
\treeroot{$\sqrt{of\ all\ evil}$}
\treeentry{Bla}{1}
\treeentry{Bla}{2}
\treeentry{Bla}{3}
\treeentry{Bla}{2}
\treeentry{Bla}{2}
\treeentry{Bla}{3}
\treeentry{Bla}{3}
\treeentry{Bla}{3}
\treeentry{Bla}{3}
\treeentry{Bla}{3}
\treeentry{Bla}{4}
\treeentry{Bla}{4}
\treeentry{Bla}{4}
\treeentry{Bla}{4}
\treeentry{Bla}{4}
\treeentry{Bla}{4}
\treeentry{Bla}{1}
\treeentry{Bla}{1}
\treeentry{Bla}{2}
\treeentry{Bla}{3}
\treeentry{Bla}{2}
\treeentry{Bla}{2}
\treeentry{Bla}{3}
\treeentry{Bla}{1}
\end{tikzpicture}
\hspace{2cm}
\begin{tikzpicture}
\treeroot{$\sqrt{of\ all\ evil}$}
\altentry{Bla}{1}
\altentry{Bla}{2}
\altentry{Bla}{3}
\altentry{Bla}{2}
\altentry{Bla}{2}
\altentry{Bla}{3}
\altentry{Bla}{3}
\altentry{Bla}{3}
\altentry{Bla}{3}
\altentry{Bla}{3}
\altentry{Bla}{4}
\altentry{Bla}{4}
\altentry{Bla}{4}
\altentry{Bla}{4}
\altentry{Bla}{4}
\altentry{Bla}{4}
\altentry{Bla}{1}
\altentry{Bla}{1}
\altentry{Bla}{2}
\altentry{Bla}{3}
\altentry{Bla}{2}
\altentry{Bla}{2}
\altentry{Bla}{3}
\altentry{Bla}{1}
\end{tikzpicture}

\end{document}

And the result:

enter image description here

share|improve this answer
add comment

I just came across this thanks to the duplicate at Vertical trees with TikZ. The following code seems to work, though I will admit to not testing it fully and making up the numbers so that it just works.

Let's start with some output:

TikZ version of dirtree

Here's the code:

\documentclass[border=10]{standalone}
\usepackage{tikz}

\makeatletter
\newcount\dirtree@lvl
\newcount\dirtree@plvl
\newcount\dirtree@clvl
\def\dirtree@growth{%
  \ifnum\tikznumberofcurrentchild=1\relax
  \global\advance\dirtree@plvl by 1
  \expandafter\xdef\csname dirtree@p@\the\dirtree@plvl\endcsname{\the\dirtree@lvl}
  \fi
  \global\advance\dirtree@lvl by 1\relax
  \dirtree@clvl=\dirtree@lvl
  \advance\dirtree@clvl by -\csname dirtree@p@\the\dirtree@plvl\endcsname
  \pgf@xa=1cm\relax
  \pgf@ya=-1cm\relax
  \pgf@ya=\dirtree@clvl\pgf@ya
  \pgftransformshift{\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
  \ifnum\tikznumberofcurrentchild=\tikznumberofchildren
  \global\advance\dirtree@plvl by -1
  \fi
}

\tikzset{
  dirtree/.style={
    growth function=\dirtree@growth,
    every node/.style={anchor=north},
    every child node/.style={anchor=west},
    edge from parent path={(\tikzparentnode\tikzparentanchor) |- (\tikzchildnode\tikzchildanchor)}
  }
}
\makeatother
\begin{document}
\begin{tikzpicture}[dirtree]
\node {toplevel} 
    child { node {Foo}
            child { node {foo} }
            child { node {bar} }
            child { node {baz} }
    }
    child { node {Bar}
        child { node {foo} }
        child { node {foo} }
        child { node {foo} }
        child { node {foo} }
        child { node {bar} }
        child { node {baz} }
    }
    child { node {Baz}
        child { node {foo} }
        child { node {bar} }
        child { node {baz} }
    };
\end{tikzpicture}
\end{document}

We define a new growth function. The idea is that we have a global counter that keeps track of how many nodes we've processed so far and position the children according to this. The main problem is that the way trees are built: the origin for each branch is the parent node. So we want to apply an absolute transformation (the total height from the root) but have to take into account the relative transformation first. This takes a bit of bookkeeping, but once that's figured out then the rest is ... plain sailing.

The edges are the easy bit - we simply define them to be |-, ie vertical and then horizontal.

share|improve this answer
    
I’ve added node anchors for better appearance with longer text. There’s also another solution on texample.net, now: texample.net/tikz/examples/filesystem-tree. –  Speravir Dec 28 '11 at 17:54
    
@Speravir Good addition, thanks. I also agree with your comment on the texample example! I'm not known for the elegance of my code here. If you can think of any further improvements to make it easier to customise, then feel free to edit the answer (or, if you feel you've done a lot of improving, then add another answer with the improved code). –  Andrew Stacey Dec 28 '11 at 20:09
1  
Worth noting the modifications from tex.stackexchange.com/q/89129/86 for better arranging the horizontal alignment. –  Andrew Stacey Jan 4 '13 at 11:21
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.