【问题标题】:What tool to use to draw file tree diagram [closed]用什么工具来绘制文件树图[关闭]
【发布时间】:2010-09-25 17:48:38
【问题描述】:

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

2012 年 2 月 20 日更新。 该问题与文档子项目有关。我必须解释文件(特别是资源和配置文件)所在的位置。 我最终使用了 dos tree 命令。我在屏幕上都抓取了结果(对于短文件夹),对于较长的文件夹,我重定向到一个文本文件,然后我对其进行了编辑。例如,如果一个子文件夹包含 20 个类似类型的文件,这些文件对我所做的点来说并不重要,我只留下两个,并将其余的替换为一个 ... 行。然后我再次将文件打印到控制台并在屏幕上抓取它。 在抓取屏幕之前,我必须将前景色修改为黑色,将背景色修改为白色,以便在打印文档时看起来更好并节省墨水。

令人惊讶的是,没有更好的工具。如果我有时间,我会编写一个 Visio Extension 或者可能是一些生成 SVG 的命令行。 SVG 不符合 HTML5 标准,甚至可以轻松包含在在线文档中。

2017 年 10 月 17 日更新。 很抱歉,这个问题因不属于 SO 而被删除。所以我重新措辞了。我需要一个脚本——而不是所见即所得的工具。所以任何脚本语言或库都可以。所以这是一个代码编写问题,我相信属于 SO。

【问题讨论】:

  • 为什么这个问题被关闭了?有编程 DSL 来绘制树:例如像graphviz这样的工具可以“以编程方式”解决这个问题。
  • 我将(暂时)重新打开它,因为如果它是一个简单的“我如何显示屏幕上的内容”,他会要求使用屏幕抓取器。如果他想画它,可能是为了设计文档或演示文稿,因此他会在某个时候进行编程。
  • 同意。我以前也需要这种相同类型的功能,并使用 Visio 来伪造它。欧盟文件需要它。肯定是代码相关的。
  • 非常愚蠢,将其关闭为题外话。我也发现需要一些东西。所以喜欢审查。
  • 如果我的问题不在此处,我很抱歉。我明白其中的原因。感谢所有提出意见的人,这很有帮助。为了澄清,我需要一个图表来包含在项目树的文档中。屏幕截图没有剪切它,因为整棵树的长度超过了一个屏幕。

标签: bash shell filesystems diagram


【解决方案1】:

从 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 — 将用于连接行的图形字符替换为 ext 字符,而不是图形字符。 /a 与不支持图形字符的代码页一起使用,并将输出发送到不能正确解释图形字符的打印机。

【讨论】:

  • 好主意,但如果文件/文件夹带有重音字母,它们将使用 OEM 字符集,而不是 Ansi 字符集。当然,对于大多数(至少会说英语的)用户来说,这可能不是问题。半图形字符也是如此。
  • Linux 也有一个像这样的“树”命令,我在查看这个 Stack Overflow 问题后才发现。感谢您指出我应该寻找的名字! “tree -A”是如何使用漂亮的绘图字符创建树;普通的“树”只是将自己限制为 ASCII。
  • 很好,我什至不知道这个命令
  • 存在许多选项,感谢大家提出这些选项。我认为这是一个答案,因为这是我最后使用的。
  • 或者直接保存到文件中:tree > file_structure.txt 我知道这适用于 Unix 系统。我不知道它是否也适用于 Windows。
【解决方案2】:

Graphviz - 来自网页:

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

这是我发现的用于创建各种框线图的最简单、最高效的工具。我拥有并使用 Visio 和 OmniGraffle,但总是很想“再做一次调整”。

编写代码来生成 Graphiz 使用的“点文件”格式也很容易,因此自动化图表生成也触手可及。

【讨论】:

    【解决方案3】:

    为什么你不能在 Windows 文件系统上创建一个文件结构并用你想要的名称填充它,然后使用像 HyperSnap(或无处不在的 Alt-PrtScr)这样的屏幕抓取工具来捕获资源管理器窗口的一部分。

    我在“演示”具有可折叠部分的互联网应用程序时这样做了,我只需要创建看起来像我想要的条目的文件。

    HyperSnap 至少提供 JPG(可能还有其他,但我从未费心去调查)。

    或者您可以从资源管理器中截取图标 +/- 并在 MS Word Draw 中使用它们来制作您的图片,但我一直无法让 MS Word Draw 正常运行。

    【讨论】:

    • Explorer 不显示嵌套文件夹,仅显示顶层。
    【解决方案4】:

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

    当我走在树上时,我制作了第一个版本的文件名。优点:没有内存开销。不便:我必须事先指定图片尺寸,所以很可能会被截断。

    所以我制作了这个版本,首先遍历目录树,将其存储在 Lua 表中。然后,知道文件的数量,创建适合(至少垂直)的画布并绘制名称。
    您可以轻松地在 PNG 渲染和 SVG 渲染之间切换。后者的问题:Cairo 在低级别生成它,绘制字母而不是使用 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")
    

    当然,您可以更改样式。我没有画连接线,我没有看到它是必要的。我以后可能会选择性地添加它们。

    【讨论】:

      【解决方案5】:

      使用 Graphviz 的建议很好:您可以生成点文件,它会完成测量字符串、布局等的艰苦工作。此外,它可以输出多种格式的图形,包括矢量格式。

      我在一个邮件列表中找到了一个正是这样做的 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,它也可以导出多种格式。它需要更多的工作(计算位置/偏移量)但结构很简单,应该不会太难。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-05
      • 2011-05-06
      • 2013-07-12
      • 2010-11-24
      • 2011-07-25
      • 2010-11-01
      相关资源
      最近更新 更多