Qué herramienta usar para dibujar un diagrama de árbol de archivos [cerrado]

90

Dado un árbol de archivos, un directorio con directorios, etc., ¿cómo escribiría un script para crear un diagrama del árbol de archivos como un archivo gráfico que pueda incrustar en un documento de procesador de texto? Prefiero archivos vectoriales (SVG, EPS, EMF ...). La herramienta debe ejecutarse en Windows, pero preferiblemente multiplataforma. La herramienta puede ser comercial, pero preferiblemente gratuita.

Actualización 2012-02-20. La pregunta estaba relacionada con un subproyecto de documentación. Tuve que explicar dónde residen los archivos (en particular, los recursos y los archivos de configuración). Terminé usando el comando dos tree. Ambos capturé la pantalla del resultado (para carpetas cortas) Y para carpetas más largas, redirigí a un archivo de texto, que luego edité. Por ejemplo, si una subcarpeta contenía 20 archivos escritos de manera similar que individualmente no eran importantes para el punto que estaba señalando, dejé solo dos y reemplacé el resto con una ... línea. Luego imprimí el archivo en la consola nuevamente y la pantalla lo capturó. Antes de capturar la pantalla, tuve que modificar el color de primer plano a negro y el color de fondo a blanco, para lucir mejor y ahorrar tinta en un documento en caso de que se imprimiera.

Es muy sorprendente que no exista una herramienta mejor para ello. Si tuviera tiempo, escribiría una extensión de Visio o podría ser alguna línea de comando que produzca SVG. SVG, al ser HTML5 deficiente, incluso permitiría una inclusión sencilla en la documentación en línea.

Actualización 2017-10-17. Lamento que esta pregunta haya sido eliminada por no pertenecer a SO. Así que lo he reformulado. Necesito un script, no una herramienta WYSIWYG. Entonces, cualquier lenguaje de programación o biblioteca está bien. Así que es una pregunta de escritura de código y creo que pertenece a SO.

Miguel
fuente
10
¿Por qué está cerrada esta pregunta? Hay DSL de programación para dibujar árboles: por ejemplo, herramientas como graphviz que pueden resolver esto "programáticamente".
Piotr Lesnicki
5
Voy a volver a abrir esto (tentativamente) porque si fuera un simple "cómo muestro lo que hay en la pantalla", habría pedido un capturador de pantalla. Si quiere dibujarlo, probablemente sea para un documento de diseño o una presentación, por lo que estará programando en algún momento.
paxdiablo
2
Convenido. He necesitado este mismo tipo de funcionalidad antes y he recurrido a falsificarlo con Visio. Lo necesitaba para la documentación de la UE. Definitivamente estaba relacionado con el código.
Joseph Ferris
6
MUY estúpido, para cerrar esto como fuera de tema. Yo también he encontrado la necesidad de algo ... ASÍ que le encanta censurar.
Boltimuss
1
Lo siento si mi pregunta está fuera de tema aquí. Entiendo la razón por la cual. Gracias a todos los que respondieron, fue útil. Para aclarar, necesitaba un diagrama para incluirlo en la documentación del árbol del proyecto. La captura de pantalla no lo corta porque todo el árbol es más largo de lo que cabe en una pantalla.
Michael

Respuestas:

95

Copiar y pegar desde el treecomando de MS-DOS también puede funcionar para usted. Ejemplos:

árbol

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

árbol / F

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

árbol / A

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

árbol / F / A

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

Sintaxis [ fuente ]

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

drive:\path - Unidad y directorio que contiene el disco para mostrar la estructura del directorio, sin listar archivos.

/F - Incluya todos los archivos que viven en cada directorio.

/A- Reemplace los caracteres gráficos utilizados para vincular líneas con caracteres ext, en lugar de caracteres gráficos. /ase utiliza con páginas de códigos que no admiten caracteres gráficos y para enviar resultados a impresoras que no interpretan correctamente los caracteres gráficos.

svinto
fuente
1
Buena idea, pero si hay archivos / carpetas con letras acentuadas, estarán en juego de caracteres OEM, no en Ansi. Probablemente no sea un problema para la mayoría de los usuarios (al menos de habla inglesa), por supuesto. Lo mismo para los caracteres semigráficos.
PhiLho
4
Linux también tiene un comando de "árbol" como este, que acabo de descubrir después de revisar esta pregunta de Stack Overflow. ¡Gracias por señalar el nombre que debería buscar! "árbol -A" es cómo crear el árbol usando bonitos personajes de dibujo; "árbol" simple se limita a ASCII.
Brandon Rhodes
1
agradable, ni siquiera conocía este comando
MiniScalope
Existen muchas opciones, gracias a todos por plantearlas. Considero que esta es una respuesta, porque eso es lo que usé al final.
Michael
1
O guárdelo directamente en un archivo: tree > file_structure.txtsé que esto funciona en sistemas Unix. No sé si también funciona en Windows.
Lucio Mollinedo
19

Graphviz - de la página web:

Los programas de diseño Graphviz toman descripciones de gráficos en un lenguaje de texto simple y crean diagramas en varios formatos útiles, como imágenes y SVG para páginas web, Postscript para su inclusión en PDF u otros documentos; o mostrar en un navegador de gráficos interactivo. (Graphviz también admite GXL, un dialecto XML).

Es la herramienta más simple y productiva que he encontrado para crear una variedad de diagramas de cajas y líneas. Tengo y uso Visio y OmniGraffle, pero siempre existe la tentación de hacer "solo un ajuste más".

También es bastante fácil escribir código para producir el formato de "archivo de puntos" que consume Graphiz, por lo que la producción automatizada de diagramas también está al alcance.

joel.neely
fuente
5

Como prometí, aquí está mi versión de El Cairo. Lo escribí con Lua, usando lfs para recorrer los directorios. Me encantan estos pequeños desafíos, ya que me permiten explorar las API que quería explorar durante bastante tiempo ...
lfs y LuaCairo son multiplataforma, por lo que debería funcionar en otros sistemas (probado en francés WinXP Pro SP3).

Hice una primera versión dibujando nombres de archivos mientras caminaba por el árbol. Ventaja: sin sobrecarga de memoria. Inconveniente: tengo que especificar el tamaño de la imagen de antemano, por lo que es probable que se corten los listados.

Así que hice esta versión, primero recorriendo el árbol de directorios y guardándola en una tabla Lua. Luego, conociendo la cantidad de archivos, creando el lienzo para que quepa (al menos verticalmente) y dibujando los nombres.
Puede cambiar fácilmente entre la representación PNG y SVG. Problema con este último: Cairo lo genera a bajo nivel, dibujando las letras en lugar de usar la capacidad de texto de SVG. Bueno, al menos, garantiza una interpretación precisa incluso en sistemas sin la fuente. Pero los archivos son más grandes ... No es realmente un problema si lo comprimes después para tener un archivo .svgz.
O no debería ser demasiado difícil generar el SVG directamente, usé Lua para generar SVG en el pasado.

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

Por supuesto, puede cambiar los estilos. No dibujé las líneas de conexión, no lo vi como necesario. Podría agregarlos opcionalmente más tarde.

PhiLho
fuente
3

¿Por qué no podría simplemente crear una estructura de archivos en el sistema de archivos de Windows y completarla con los nombres deseados, luego usar un capturador de pantalla como HyperSnap (o el omnipresente Alt-PrtScr) para capturar una sección de la ventana del Explorador?

Hice esto cuando hice una 'demostración' de una aplicación de Internet que tendría secciones plegables, solo tuve que crear archivos que se parecieran a mis entradas deseadas.

HyperSnap ofrece JPG al menos (probablemente otros, pero nunca me he molestado en investigar).

O puede capturar en pantalla los íconos +/- de Explorer y usarlos dentro de MS Word Draw para hacer su imagen, pero nunca he podido hacer que MS Word Draw se comporte correctamente.

paxdiablo
fuente
2

El consejo para usar Graphviz es bueno: puede generar el archivo de puntos y hará el trabajo duro de medir cadenas, hacer el diseño, etc. Además, puede generar los gráficos en muchos formatos, incluidos los vectoriales.

Encontré un programa de Perl haciendo precisamente eso, en una lista de correo, ¡pero no puedo encontrarlo! Copié el archivo de puntos de muestra y lo estudié, ya que no sé mucho de esta sintaxis declarativa y quería aprender un poco más.

Problema: con el último Graphviz, tengo errores (o más bien, advertencias, ya que se genera el diagrama final), tanto en el gráfico original como en el que escribí (a mano). Algunas búsquedas mostraron que este error se encontró en versiones antiguas y desapareció en versiones más recientes. Parece que ha vuelto.

Todavía le doy el archivo, tal vez pueda ser un punto de partida para alguien, o tal vez sea suficiente para sus necesidades (por supuesto, todavía tiene que generarlo).

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

Intentaré en otra dirección, usando Cairo, que también puede exportar varios formatos. Es más trabajo (calcular posiciones / compensaciones) pero la estructura es simple, no debería ser demasiado difícil.

PhiLho
fuente
1
Steve DeRose tiene una estructura de archivos de creación de Perlscript -> archivo de puntos en derose.net/steve/utilities
claj