用什么工具绘制文件树图

给定一个文件树 – 一个包含目录的目录等等,你将如何编写一个脚本来创build一个文件树的图表作为一个graphics文件,我可以embedded到一个文字处理器文档中。 我更喜欢vector(SVG,EPS,EMF …)文件。 该工具必须在Windows上运行,但最好是跨平台的。 该工具可能是商业的,但最好是免费的。

更新2012-02-20。 这个问题涉及到一个文档子项目。 我不得不解释文件(特别是资源和configuration文件)在哪里。 我结束了使用DOS树命令。 我都屏幕抓住了结果(短文件夹)和较长的文件夹我redirect到一个文本文件,然后我编辑。 例如,如果一个子文件夹包含20个类似的文件,这些文件对于我所创build的点来说并不重要,我只剩下两个文件,用其中一行代替。 然后我打印出来的文件再次控制和屏幕抓住它。 抓屏之前,我必须修改前景颜色为黑色和背景色为白色,看起来更好,并节省墨水应该打印文档。

它是没有更好的工具是非常令人惊讶的。 如果我有时间,我会写一个Visio扩展,或者可能是一些生成SVG的命令行。 SVG是HTML5的不合格标准,甚至可以轻松纳入在线文档。

更新2017-10-17。 对不起,这个问题被删除,因为不属于SO。 所以我重新措辞。 我需要一个脚本 – 而不是一个所见即所得的。 所以任何脚本语言或库都可以。 所以这是一个代码写作的问题,我相信属于SO。

从MS-DOS tree命令复制和粘贴也可能适用于您。 例子:

 C:\Foobar>tree C:. ├───FooScripts ├───barconfig ├───Baz │ ├───BadBaz │ └───Drop ... 

树/ F

 C:\Foobar>tree C:. ├───FooScripts │ foo.sh ├───barconfig │ bar.xml ├───Baz │ ├───BadBaz │ │ badbaz.xml │ └───Drop ... 

树/ A

 C:\Foobar>tree /A C:. +---FooScripts +---barconfig +---Baz ¦ +---BadBaz ¦ \---Drop ... 

树/ F / A

 C:\Foobar>tree /A C:. +---FooScripts ¦ foo.sh +---barconfig ¦ bar.xml +---Baz ¦ +---BadBaz ¦ ¦ badbaz.xml ¦ \---Drop ... 

语法[ source ]

tree [ drive: ] [ path ] [ /F ] [ /A ]

drive:\path – 包含磁盘的驱动器和目录,用于显示目录结构,无需列出文件。

/F – 包含每个目录中的所有文件。

/A – 将用于链接行的graphics字符replace为ext字符,而不是graphics字符。 /a与不支持graphics字符的代码页一起使用,并将输出发送到不正确解释graphics字符的打印机。

Graphviz – 来自网页:

Graphviz布局程序以简单的文本语言描述graphics,并以几种有用的格式制作图表,如用于网页的图像和SVG,用于包含在PDF或其他文档中的Postscript; 或在交互式graphics浏览器中显示。 (Graphviz还支持XML方言GXL。)

这是我发现创build各种各样的方框图的最简单和最有效率的工具。 我已经使用了Visio和OmniGraffle,但总是有一种“多一个调整”的诱惑。

编写代码来生成Graphiz消耗的“点文件”格式也很容易,所以自动化的图生成也很容易达到。

如承诺,这是我的开罗版本。 我用Lua编写脚本,使用lfs来遍历目录。 我喜欢这些小挑战,因为它们让我探索我想挖掘相当一段时间的API。
lfs和LuaCairo都是跨平台的,所以它应该可以在其他系统上运行(在法语WinXP Pro SP3上testing)。

我走树的时候做了第一个绘制文件名的版本。 优点:没有内存开销。 不方便:我必须事先指定图片大小,所以列表可能会被切断。

所以我做了这个版本,首先走目录树,把它存储在一个Lua表中。 然后,知道文件的数量,创buildcanvas以适应(至less垂直)和绘制名称。
您可以轻松地在PNG渲染和SVG之间切换。 后者的问题:开罗在较低的层次上生成它,而不是使用SVG的文本能力来绘制字母。 那么,至less,它确保即使在没有字体的系统上也能够准确的再现。 但是这些文件比较大……如果你压缩之后,就不会有问题了,要有一个.svgz文件。
或者直接生成SVG应该不会太难,过去我使用Lua生成SVG。

 -- LuaFileSystem <http://www.keplerproject.org/luafilesystem/> require"lfs" -- LuaCairo <http://www.dynaset.org/dogusanh/> require"lcairo" local CAIRO = cairo local PI = math.pi local TWO_PI = 2 * PI --~ local dirToList = arg[1] or "C:/PrgCmdLine/Graphviz" --~ local dirToList = arg[1] or "C:/PrgCmdLine/Tecgraf" local dirToList = arg[1] or "C:/PrgCmdLine/tcc" -- Ensure path ends with / dirToList = string.gsub(dirToList, "([^/])$", "%1/") print("Listing: " .. dirToList) local fileNb = 0 --~ outputType = 'svg' outputType = 'png' -- dirToList must have a trailing slash function ListDirectory(dirToList) local dirListing = {} for file in lfs.dir(dirToList) do if file ~= ".." and file ~= "." then local fileAttr = lfs.attributes(dirToList .. file) if fileAttr.mode == "directory" then dirListing[file] = ListDirectory(dirToList .. file .. '/') else dirListing[file] = "" end fileNb = fileNb + 1 end end return dirListing end --dofile[[../Lua/DumpObject.lua]] -- My own dump routine local dirListing = ListDirectory(dirToList) --~ print("\n" .. DumpObject(dirListing)) print("Found " .. fileNb .. " files") --~ os.exit() -- Constants to change to adjust aspect local initialOffsetX = 20 local offsetY = 50 local offsetIncrementX = 20 local offsetIncrementY = 12 local iconOffset = 10 local width = 800 -- Still arbitrary local titleHeight = width/50 local height = offsetIncrementY * (fileNb + 1) + titleHeight local outfile = "CairoDirTree." .. outputType local ctxSurface if outputType == 'svg' then ctxSurface = cairo.SvgSurface(outfile, width, height) else ctxSurface = cairo.ImageSurface(CAIRO.FORMAT_RGB24, width, height) end local ctx = cairo.Context(ctxSurface) -- Display a file name -- file is the file name to display -- offsetX is the indentation function DisplayFile(file, bIsDir, offsetX) if bIsDir then ctx:save() ctx:select_font_face("Sans", CAIRO.FONT_SLANT_NORMAL, CAIRO.FONT_WEIGHT_BOLD) ctx:set_source_rgb(0.5, 0.0, 0.7) end -- Display file name ctx:move_to(offsetX, offsetY) ctx:show_text(file) if bIsDir then ctx:new_sub_path() -- Position independent of latest move_to -- Draw arc with absolute coordinates ctx:arc(offsetX - iconOffset, offsetY - offsetIncrementY/3, offsetIncrementY/3, 0, TWO_PI) -- Violet disk ctx:set_source_rgb(0.7, 0.0, 0.7) ctx:fill() ctx:restore() -- Restore original settings end -- Increment line offset offsetY = offsetY + offsetIncrementY end -- Erase background (white) ctx:set_source_rgb(1.0, 1.0, 1.0) ctx:paint() --~ ctx:set_line_width(0.01) -- Draw in dark blue ctx:set_source_rgb(0.0, 0.0, 0.3) ctx:select_font_face("Sans", CAIRO.FONT_SLANT_NORMAL, CAIRO.FONT_WEIGHT_BOLD) ctx:set_font_size(titleHeight) ctx:move_to(5, titleHeight) -- Display title ctx:show_text("Directory tree of " .. dirToList) -- Select font for file names ctx:select_font_face("Sans", CAIRO.FONT_SLANT_NORMAL, CAIRO.FONT_WEIGHT_NORMAL) ctx:set_font_size(10) offsetY = titleHeight * 2 -- Do the job function DisplayDirectory(dirToList, offsetX) for k, v in pairs(dirToList) do --~ print(k, v) if type(v) == "table" then -- Sub-directory DisplayFile(k, true, offsetX) DisplayDirectory(v, offsetX + offsetIncrementX) else DisplayFile(k, false, offsetX) end end end DisplayDirectory(dirListing, initialOffsetX) if outputType == 'svg' then cairo.show_page(ctx) else --cairo.surface_write_to_png(ctxSurface, outfile) ctxSurface:write_to_png(outfile) end ctx:destroy() ctxSurface:destroy() print("Found " .. fileNb .. " files") 

当然,你可以改变风格。 我没有画出连接线,我没有看到它是必要的。 我可能稍后添加它们。

为什么不能只在Windows文件系统上创build一个文件结构,然后用你想要的名字来填充文件结构,然后使用一个像HyperSnap(或无处不在的Alt-PrtScr)这样的抓屏程序来捕获资源pipe理器窗口的一部分。

当“演示”一个互联网应用程序,这将有可折叠的部分,我做到了这一点,我只需要创build看起来像我想要的条目的文件。

HyperSnap至less可以提供JPG格式(可能还有其他的格式,但我从来没有打扰到过)。

或者你可以从资源pipe理器中捕获图标+/-并在MS Word中使用它们绘制自己的图片,但是我从来没有能够得到MS Word Draw的正确performance。

使用Graphviz的build议是很好的:你可以生成点文件,它会做测量string,做布局等等的辛苦工作。另外,它可以以很多格式输出graphics,包括vectorgraphics。

我发现一个Perl程序正在做一个邮件列表,但我找不到它! 我复制了示例点文件并对其进行了研究,因为我不太了解这种声明性语法,所以我想了解更多。

问题:在最新的Graphviz中,我在原始图和我写的(手工)中都有错误(或者说,生成最终图的警告)。 一些search显示这个错误是在旧版本中发现,并在更新的版本中消失。 看起来像是回来了。

我仍然给这个文件,也许它可以成为某个人的起点,或者这对你的需求来说已经足够了(当然,你仍然需要生成它)。

 digraph tree { rankdir=LR; DirTree [label="Directory Tree" shape=box] a_Foo_txt [shape=point] f_Foo_txt [label="Foo.txt", shape=none] a_Foo_txt -> f_Foo_txt a_Foo_Bar_html [shape=point] f_Foo_Bar_html [label="Foo Bar.html", shape=none] a_Foo_Bar_html -> f_Foo_Bar_html a_Bar_png [shape=point] f_Bar_png [label="Bar.png", shape=none] a_Bar_png -> f_Bar_png a_Some_Dir [shape=point] d_Some_Dir [label="Some Dir", shape=ellipse] a_Some_Dir -> d_Some_Dir a_VBE_C_reg [shape=point] f_VBE_C_reg [label="VBE_C.reg", shape=none] a_VBE_C_reg -> f_VBE_C_reg a_P_Folder [shape=point] d_P_Folder [label="P Folder", shape=ellipse] a_P_Folder -> d_P_Folder a_Processing_20081117_7z [shape=point] f_Processing_20081117_7z [label="Processing-20081117.7z", shape=none] a_Processing_20081117_7z -> f_Processing_20081117_7z a_UsefulBits_lua [shape=point] f_UsefulBits_lua [label="UsefulBits.lua", shape=none] a_UsefulBits_lua -> f_UsefulBits_lua a_Graphviz [shape=point] d_Graphviz [label="Graphviz", shape=ellipse] a_Graphviz -> d_Graphviz a_Tree_dot [shape=point] f_Tree_dot [label="Tree.dot", shape=none] a_Tree_dot -> f_Tree_dot { rank=same; DirTree -> a_Foo_txt -> a_Foo_Bar_html -> a_Bar_png -> a_Some_Dir -> a_Graphviz [arrowhead=none] } { rank=same; d_Some_Dir -> a_VBE_C_reg -> a_P_Folder -> a_UsefulBits_lua [arrowhead=none] } { rank=same; d_P_Folder -> a_Processing_20081117_7z [arrowhead=none] } { rank=same; d_Graphviz -> a_Tree_dot [arrowhead=none] } } > dot -Tpng Tree.dot -o Tree.png Error: lost DirTree a_Foo_txt edge Error: lost a_Foo_txt a_Foo_Bar_html edge Error: lost a_Foo_Bar_html a_Bar_png edge Error: lost a_Bar_png a_Some_Dir edge Error: lost a_Some_Dir a_Graphviz edge Error: lost d_Some_Dir a_VBE_C_reg edge Error: lost a_VBE_C_reg a_P_Folder edge Error: lost a_P_Folder a_UsefulBits_lua edge Error: lost d_P_Folder a_Processing_20081117_7z edge Error: lost d_Graphviz a_Tree_dot edge 

我会尝试另一个方向,使用开罗,这也是能够出口一些格式。 这是更多的工作(计算职位/抵消),但结构简单,不应该太难。