给定一个文件树 - 一个包含目录的目录等,你如何编写一个脚本来创建一个文件树图表作为一个图形文件,我可以嵌入一个文字处理器文档。 我更喜欢矢量(SVG,EPS,EMF ...)文件。 该工具必须在Windows上运行,但最好是跨平台的。 该工具可以是商业的,但最好是免费的。
更新2012-02-20。 这个问题与文档子项目有关。我不得不解释文件(特别是资源和配置文件)所在的位置。 我最终使用了dos tree命令。我两个屏幕抓取结果(对于短文件夹)和更长的文件夹我重定向到文本文件,然后我编辑。例如,如果一个子文件夹包含20个类似类型的文件,这些文件分别对我正在制作的点不重要,我只剩下两个并用一个......替换其余的文件。然后我再次将文件打印到控制台,屏幕抓住了它。 在屏幕抓取之前,我不得不将前景颜色修改为黑色,将背景颜色修改为白色,以便在打印时更好地保存文档中的墨水。
令人惊讶的是,它没有更好的工具。如果我有时间,我会写一个Visio扩展,或者可能是一些产生SVG的命令行。 SVG是HTML5不合格的,甚至可以轻松地包含在在线文档中。
2017-10-17更新。 对不起,这个问题因为不属于SO而被删除了。所以我已经重新措辞了。我需要一个脚本 - 而不是WYSIWYG。所以任何脚本语言或库都可以。所以这是一个代码编写问题,我相信属于SO。
答案 0 :(得分:76)
从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
...
tree
[drive:
] [path
] [/F
] [/A
]
drive:\path
- 包含磁盘的驱动器和目录,用于显示目录结构,不包含列表文件。
/F
- 包含生活在每个目录中的所有文件。
/A
- 将用于链接行的图形字符替换为ext字符,而不是图形字符。/a
用于不支持图形字符的代码页,并将输出发送到不能正确解释图形字符的打印机。
答案 1 :(得分:18)
Graphviz - 来自网页:
Graphviz布局程序以简单的文本语言描述图形,并以几种有用的格式绘制图表,例如网页的图像和SVG,包含在PDF或其他文档中的Postscript;或在交互式图形浏览器中显示。 (Graphviz还支持XML方言GXL。)
这是我发现创建各种盒线图的最简单,最高效的工具。我有和使用Visio和OmniGraffle,但总是有诱惑“只需再调整一次”。
编写代码以生成Graphiz消耗的“点文件”格式也非常容易,因此自动化图表生成也很容易实现。
答案 2 :(得分:5)
正如所承诺的,这是我的开罗版本。我用Lua编写脚本,使用lfs来遍历目录。我喜欢这些小挑战,因为他们允许我探索我想挖掘的API很长一段时间...... lfs和LuaCairo都是跨平台的,因此它应该适用于其他系统(在法语WinXP Pro SP3上测试)。
当我走过树时,我制作了第一个绘制文件名的版本。优点:没有内存开销。不便之处:我必须事先指定图像尺寸,因此列表可能会被切断。
所以我制作了这个版本,首先走到目录树,将其存储在Lua表中。然后,知道文件的数量,创建适合(至少垂直)的画布并绘制名称 您可以轻松地在PNG渲染和SVG渲染之间切换。后者的问题:开罗在低级别生成它,绘制字母而不是使用SVG的文本功能。好吧,至少,即使在没有字体的系统上,它也能保证准确的结果。但是文件更大......如果你压缩它之后没有真正的问题,有一个.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")
当然,您可以更改样式。我没有绘制连接线,我没有看到它的必要。我可以稍后选择添加它们。
答案 3 :(得分:3)
为什么你不能只在Windows文件系统上创建一个文件结构并用你想要的名字填充它,然后使用像HyperSnap(或无处不在的Alt-PrtScr)这样的屏幕抓取器来捕获资源管理器窗口的一部分。 / p>
我在“演示”具有可折叠部分的互联网应用程序时这样做,我只需要创建看起来像我想要的条目的文件。
HyperSnap至少提供JPG(可能是其他人,但我从未打扰过调查)。
或者您可以从资源管理器中屏幕捕获图标+/-并在MS Word Draw中使用它们来制作您的照片,但我从来没有能够让MS Word Draw正常运行。
答案 4 :(得分:2)
使用Graphviz的建议很好:你可以生成点文件,它将完成测量字符串,进行布局等的艰苦工作。此外,它可以输出多种格式的图形,包括矢量格式。 / p>
我发现一个Perl程序正是在邮件列表中完成,但我找不到它!我复制了示例点文件并对其进行了研究,因为我对这种声明性语法知之甚少,而且我想学习更多。
问题:对于最新的Graphviz,我在原始图形和我编写的图形(手动)中都有错误(或者更确切地说,警告,生成最终图表)。一些搜索显示此错误在旧版本中找到,并在更新版本中消失。看起来好像回来了。
我仍然提供文件,也许它可以作为某人的起点,或者它可能足以满足您的需求(当然,您仍需要生成它)。
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
我将尝试另一个方向,使用Cairo,它也能够导出多种格式。这是更多的工作(计算位置/偏移)但结构很简单,不应该太难。