What tool to use to draw a file tree diagram

Given the file tree - a directory with directories in it, etc., How would you write a script to create a file tree diagram as a graphic file that I can embed in a word processor document. I prefer vector (SVG, EPS, EMF ...) files. The tool should work on Windows, but preferably cross-platform. The tool may be commercial, but preferably free.

Update 2012-02-20. The question was related to the documentation subproject. I had to explain where the files are located (in particular, resources and configuration files). I ended up using the dos tree command. I captured the result on both screens (for short folders) And for longer folders I redirected to a text file, which I then edited. For example, if a subfolder contained 20 files of the same type, which individually were not important for what I was doing, I left only two, and replaced the rest with one ... line. Then I again printed the file to the console, and the screen grabbed it. Before capturing the screen, I had to change the foreground color to black and the background color to white in order to look better and save ink in the document that needs to be printed.

It is very surprising that there is no better tool for this. If I had time, I would write a Visio extension or maybe some kind of command line that produces SVG. SVG, being low-quality HTML5, will allow even painless inclusion in online documentation.

Update 2017-10-17. I am sorry this question has been removed as not belonging to SO. So I rephrased this. I need a script, not a WYSIWYG tool. So any scripting language or library is fine. So this is a question of writing code, and I believe that it belongs to SO.

+76
bash filesystems shell diagram
Dec 07 '08 at 13:01
source share
5 answers

Copying and pasting from the MS-DOS tree command may also work for you. Examples:

wood

 C:\Foobar>tree C:. β”œβ”€β”€β”€FooScripts β”œβ”€β”€β”€barconfig β”œβ”€β”€β”€Baz β”‚ β”œβ”€β”€β”€BadBaz β”‚ └───Drop ... 

tree / f

 C:\Foobar>tree C:. β”œβ”€β”€β”€FooScripts β”‚ foo.sh β”œβ”€β”€β”€barconfig β”‚ bar.xml β”œβ”€β”€β”€Baz β”‚ β”œβ”€β”€β”€BadBaz β”‚ β”‚ badbaz.xml β”‚ └───Drop ... 

tree / A

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

wood / f / a

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

Syntax [ source ]

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

drive:\path - The drive and directory containing the drive to display the directory structure, without listing files.

/F - Include all files living in each directory.

/A - Replace graphic characters used to associate strings with external characters instead of graphic characters. /A used with code pages that do not support graphic characters and send output to printers that incorrectly interpret graphic characters.

+79
Dec 07 '08 at 13:32
source share

Graphviz - from the web page:

Graphviz layout programs describe graphs in plain text and make diagrams in several useful formats, such as images and SVGs for web pages, Postscript for inclusion in PDF or other documents; or display in an interactive graphical browser. (Graphviz also supports GXL, an XML dialect).

This is the easiest and most effective tool I have found for creating various box and line diagrams. I use Visio and OmniGraffle, but there is always the temptation to do "one more setting."

It's also pretty easy to write code to create the "dot file" format that Graphiz consumes, so automatic charting is also great.

+19
Dec 07 '08 at 13:25
source share

As promised, here is my Cairo version. I wrote it using Lua, using lfs to go around directories. I like these little problems, as they allow me to explore the APIs that I have long wanted to dig ...
lfs and LuaCairo are cross-platform, so it should work on other systems (tested on French WinXP Pro SP3).

I made the drawing file names of the first version as I walked through the tree. Advantage: no memory overhead. Inconvenience: I have to specify the size of the image in advance, so lists are likely to be disabled.

So, I made this version by first breaking through the directory tree, saving it in the Lua table. Then, knowing the number of files, creating a canvas so that it fits (at least vertically) and draws the names.
You can easily switch between PNG and SVG rendering. The problem with the latter: Cairo generates it at a low level, drawing letters instead of using the SVG text feature. Well, at the very least, this ensures accurate breaks even on non-font systems. But the files are bigger ... Not a problem if you compress it to have a .svgz file.
Or it should not be too difficult to create SVG directly, I used Lua to generate SVG in the past.

 -- 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") 

Of course you can change the styles. I did not draw communication lines, I did not see it as needed. I can add them later.

+5
Dec 09 '08 at 0:39
source share

Why don't you just create a file structure in the Windows file system and fill it with the necessary names, and then use a screen capture such as HyperSnap (or the ubiquitous Alt-PrtScr) to capture a section of the explorer window.

I did this when I β€œunmounted” an Internet application that would have legible sections, I just needed to create files similar to my desired entries.

HyperSnap gives JPG at least (maybe others, but I never bothered to investigate).

Or you can display the +/- icons from Explorer and use them in the MS Word Draw program itself to make your image, but I could never make MS Word Draw behave correctly.

+3
Dec 07 '08 at 13:23
source share

The tip on using Graphviz is good: you can generate a point file and it will do the hard work of measuring rows, executing layout, etc. In addition, it can output graphics in a variety of formats, including vector.

I found a Perl program that does just that on the mailing list, but I just can't find it back! I copied a sample point file and studied it, since I know little about this declarative syntax, and I wanted to know a little more.

Problem: with the latest Graphviz, I have errors (or rather warnings, since the final diagram is generated), both in the original graph and in what I wrote (manually). Some searches that showed this error were found in older versions and disappeared in later versions. It looks like he is back.

I am still giving the file, maybe this may be the starting point for someone, or maybe this is enough for your needs (of course, you should still generate it).

 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 

I will try a different direction using Cairo, which can also export multiple formats. This is more work (computational positions / offsets), but the structure is simple, should not be too complicated.

+2
Dec 07 '08 at 22:49
source share



All Articles