使用 tikz 自动生成递归文件层次结构(目录树)图

使用 tikz 自动生成递归文件层次结构(目录树)图

所以,我一直在尝试编写一个python脚本来生成Ti以下文件系统树/目录结构图之一的 Z/LaTeX 源代码:

预览


代码

LaTeX:钛

\documentclass[tikz,border=10]{standalone}
\usetikzlibrary{trees}
\tikzstyle{every node}=[draw=black,thick,anchor=west]

\begin{document}

    \begin{tikzpicture}[ %
    grow via three points={one child at (0.5,-0.7) and two children at (0.5,-0.7) and (0.5,-1.4)},
    edge from parent path={(\tikzparentnode.south)|-(\tikzchildnode.west)}]

        \node {/tmp/test}
        %
        child{node{a}
            child{node{1}}
            child{node{2}}
            child{node{3}}}
        child [missing] {} %
        child [missing] {} %
        child [missing] {} %
        %
        child{node{b}
            child{node{1}}
            child{node{2}}}
        child [missing] {} %
        child [missing] {} %
        %
        child{node{c}
            child{node{1}}}
        child [missing] {} %
        %
        child{node{d}};
        %
    \end{tikzpicture}

\end{document}

这本来应该是一件小事,但事实证明,编写程序可能会非常令人困惑。如果可能的话,我希望有一种在 LaTeX 环境中完成所有操作的方法(也许 LuaLaTeX 可以提供帮助?)。或者,某种宏或函数可以以实用格式接受输入,这些格式可以在外部生成并复制/粘贴。以下是一些可能适合的生成输入的方法的示例(我只是随便举几个例子,它们并不完美,但我可以根据需要进行调整):


附加信息:

不要被这一部分搞糊涂了,问题不是关于 bash 或 python 或其他什么,这只是为了演示几种生成输入的方法,也是为了展示它可以轻松地被处理成适当的格式。我需要的帮助是编写一个合适的 LaTeX 宏,可以正确排版这些信息。

bash:查找

find .

出去

.
./a
./a/1
./a/2
./a/3
./b
./b/1
./b/2
./c
./c/1
./d

printf '{/tmp/test'; 
find /tmp/test -printf '%P, ';
printf '}\n';

出去

{tmp/test, a, a/1, a/2, a/3, b, b/1, b/2, c, c/1, d, }

python: os.walk()

import os
for (root,dirs,files) in os.walk('.'):
    print(f'{root}\n{dirs}\n{files}')

出去

.
['a', 'b', 'c', 'd']
[]
./a
[]
['1', '2', '3']
./b
[]
['1', '2']
./c
[]
['1']
./d
[]
[]

print('{/tmp/test',end='')
for (root,dirs,files) in os.walk('.'):
    print(f"{root[2:]},[{','.join(dirs+files)}],")
print('}')

出去

{/tmp/test,[a,b,c,d],
a,[1,2,3],
b,[1,2],
c,[1],
d,[],
}

答案1

这不是一个答案(但它太长了,无法放入评论中)。我认为可以使用-shell-escapetree命令和一些(我比regex更熟悉)来实现。第一件事是能够找到一个模式,以便能够在其中构建代码。使用:perlpythontikz

[pablo@worktex ~] $ pwd
/home/pablo
[pablo@worktex ~] $ tree ltxgit/
ltxgit/
├── build
│   ├── distrib
│   ├── doc
│   ├── local
│   ├── test
│   └── unpacked
├── build.lua
├── mybuild.lua
├── mygitcmd.txt
├── mytree.txt
├── README.md
├── sources
│   ├── README.md
│   └── testfiles
│       ├── test-nospace.tex
│       └── test-pkg.tex
└── texlive
    ├── texlive_install.sh
    ├── texlive_packages
    └── texlive.profile

9 directories, 11 files

重点是区分哪些是目录,哪些只是文件,然后我们切换到:

[pablo@worktex ~] $ tree -p ltxgit/
ltxgit/
├── [drwxrwxr-x]  build
│   ├── [drwxrwxr-x]  distrib
│   ├── [drwxrwxr-x]  doc
│   ├── [drwxrwxr-x]  local
│   ├── [drwxrwxr-x]  test
│   └── [drwxrwxr-x]  unpacked
├── [-rw-rw-r--]  build.lua
├── [-rw-rw-r--]  mybuild.lua
├── [-rw-rw-r--]  mygitcmd.txt
├── [-rw-rw-r--]  mytree.txt
├── [-rw-rw-r--]  README.md
├── [drwxrwxr-x]  sources
│   ├── [-rw-rw-r--]  README.md
│   └── [drwxrwxr-x]  testfiles
│       ├── [-rw-rw-r--]  test-nospace.tex
│       └── [-rw-rw-r--]  test-pkg.tex
└── [drwx------]  texlive
    ├── [-rw-rw-r--]  texlive_install.sh
    ├── [-rw-rw-r--]  texlive_packages
    └── [-rw-rw-r--]  texlive.profile

9 directories, 11 files

使用 区分目录和文件-p。现在到了最难的部分,找到将代码传递给 的规律tikz。我们知道第一行对应于根目录,其他行遵循基于行首|、空格及其标识 的规律[d.+?]。我们可以生成一个例程并将其转换为:

ltxgit/
├── build/
│   ├── distrib/
│   ├── doc/
│   ├── local/
│   ├── test/
│   └── unpacked/
├── build.lua
├── mybuild.lua
├── mygitcmd.txt
├── mytree.txt
├── README.md
├── sources/
│   ├── README.md
│   └── testfiles/
│       ├── test-nospace.tex
│       └── test-pkg.tex
└── texlive/
    ├── texlive_install.sh
    ├── texlive_packages
    └── texlive.profile

就 而言tikz。我认为(我对此不确定)最好使用Lua并在多平台上进行操作,而不依赖于tree,但是,如果您正在使用,python也许您可​​以玩一段时间,pythontex直到找到解决方案。

祝你好运,看到它发挥作用真是太棒了。

答案2

您可以执行类似以下的操作。这依赖于tree系统中存在的命令,以及 和bash---sed因此这在 Windows 上是无用的,例如 --- 但是,如果启用了 shell 转义,则该命令将作为编译的一部分在外部运行。

\documentclass{article}
\usepackage{bashful}
\usepackage[edges]{forest}
\begin{document}
\bash[stdoutFile=mydirtree.tex]
tree -X --noreport /opt/stapler/ | sed -e "s/<tree>/\\\begin{forest}for tree={folder,grow\'=0}/" -e 's/<\/tree>/\\end{forest}/' -e 's/\(<directory name=\)\|\(<file name=\)/[/' -e's/\"\([^\"]*\)\">/\1/' -e 's/<\/directory>/]/' -e 's/<\/file>/]/' -e '/^<?xml version/d' -e 's/_/\\_/g'
\END
\input{mydirtree}

\end{document}

目录列表

请注意,您可能需要sed根据系统中文件名中出现的字符进行调整(当然包括目录,它们也是文件)。

我曾经pdflatex -shell-escape <filename>编译过。

相关内容