Que ferramenta usar para desenhar o diagrama de árvore de arquivos [fechado]

92

Dada uma árvore de arquivos - um diretório com diretórios etc, como você escreveria um script para criar um diagrama da árvore de arquivos como um arquivo gráfico que eu possa incorporar em um documento de processador de texto. Eu prefiro arquivos vetoriais (SVG, EPS, EMF ...). A ferramenta deve ser executada no Windows, mas preferencialmente em plataforma cruzada. A ferramenta pode ser comercial, mas de preferência gratuita.

Atualização 20/02/2012. A pergunta estava relacionada a um subprojeto de documentação. Tive que explicar onde os arquivos (em particular recursos e arquivos de configuração) residem. Acabei usando o comando DOS Tree. Eu peguei o resultado na tela (para pastas curtas) E para pastas mais longas redirecionei para um arquivo de texto, que editei. Por exemplo, se uma subpasta continha 20 arquivos com tipos semelhantes que individualmente não eram importantes para o ponto que eu estava defendendo, deixei apenas dois e substituí o restante por uma ... linha. Em seguida, imprimi o arquivo para o console novamente e a tela o capturou. Antes de capturar a tela, tive que modificar a cor de primeiro plano para preto e a cor de fundo para branco, para ter uma aparência melhor e economizar tinta em um documento que deveria ser impresso.

É muito surpreendente que não haja ferramenta melhor para isso. Se eu tivesse tempo, escreveria uma Extensão do Visio ou pode ser alguma linha de comando que produza SVG. Por ser o HTML5 abaixo do padrão, o SVG até permitiria a inclusão indolor na documentação online.

Atualização 2017-10-17. Lamento que esta questão tenha sido removida por não pertencer a SO. Então eu o reformulei. Preciso de um script - não de uma ferramenta WYSIWYG. Portanto, qualquer linguagem de script ou biblioteca está ok. Portanto, é uma questão de escrita de código, e acredito que pertence ao SO.

Michael
fonte
10
Por que esta questão está fechada? Existem DSLs de programação para desenhar árvores: por exemplo, ferramentas como o Graphviz, que podem resolver isso "programaticamente".
Piotr Lesnicki
5
Vou reabrir (provisoriamente) porque se fosse um simples "como faço para mostrar o que está na tela", ele teria pedido um agarrador de tela. Se ele quiser desenhá-lo, provavelmente será para um documento de design ou apresentação, portanto, ele estará programando em algum momento.
paxdiablo
2
Acordado. Eu precisei desse mesmo tipo de funcionalidade antes e recorri a fingi-lo com o Visio. Necessário para documentação da UE. Definitivamente estava relacionado ao código.
Joseph Ferris
6
MUITO estúpido, para fechar isso como fora do tópico. Eu também encontrei a necessidade de algo. POR ISSO adora censurar.
Boltimuss de
1
Sinto muito se minha pergunta está fora do assunto aqui. Eu entendo o motivo. Obrigado a todos aqueles que responderam, foi útil. Para esclarecer, eu precisava de um diagrama para incluir na documentação da árvore do projeto. A captura de tela não corta porque a árvore inteira é mais longa do que cabe em uma tela.
Michael

Respostas:

98

Copiar e colar a partir do treecomando do MS-DOS também pode funcionar para você. Exemplos:

árvore

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

árvore / F

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

árvore / A

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

árvore / F / A

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

Sintaxe [ fonte ]

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

drive:\path - Drive e diretório contendo disco para exibição da estrutura do diretório, sem listar arquivos.

/F - Inclui todos os arquivos que vivem em cada diretório.

/A- Substitua os caracteres gráficos usados ​​para vincular as linhas por caracteres ext, em vez de caracteres gráficos. /aé usado com páginas de código que não oferecem suporte a caracteres gráficos e para enviar saída para impressoras que não interpretam corretamente os caracteres gráficos.

svinto
fonte
1
Boa ideia, mas se houver arquivos / pastas com letras acentuadas, eles estarão em conjunto de caracteres OEM, não em Ansi. Provavelmente um não-problema para a maioria dos usuários (pelo menos falando inglês), é claro. O mesmo para caracteres semigráficos.
PhiLho
4
O Linux também tem um comando "tree" como este, que acabei de descobrir depois de verificar esta questão do Stack Overflow. Obrigado por apontar o nome que devo procurar! "tree -A" é como criar a árvore usando personagens de desenho bonitos; a "árvore" simples limita-se ao ASCII.
Brandon Rhodes,
1
legal, eu nem conhecia esse comando
MiniScalope
Existem muitas opções, obrigado a todos por mencioná-las. Considero esta uma resposta, porque foi o que acabei por usar.
Michael
1
Ou salve-o diretamente em um arquivo: tree > file_structure.txtEu sei que isso funciona em sistemas Unix. Não sei se funciona no Windows também.
Lucio Mollinedo
19

Graphviz - na página da web:

Os programas de layout Graphviz obtêm descrições de gráficos em uma linguagem de texto simples e fazem diagramas em vários formatos úteis, como imagens e SVG para páginas da web, Postscript para inclusão em PDF ou outros documentos; ou exibir em um navegador gráfico interativo. (Graphviz também suporta GXL, um dialeto XML.)

É a ferramenta mais simples e produtiva que encontrei para criar uma variedade de diagramas de caixas e linhas. Tenho e uso Visio e OmniGraffle, mas sempre há a tentação de fazer "apenas mais um ajuste".

Também é muito fácil escrever código para produzir o formato de "arquivo de ponto" que o Graphiz consome, portanto, a produção automatizada de diagramas também está ao seu alcance.

joel.neely
fonte
5

Como prometido, aqui está minha versão do Cairo. Eu fiz um script com Lua, usando lfs para percorrer os diretórios. Eu amo esses pequenos desafios, pois eles me permitem explorar APIs que eu queria cavar há algum tempo ...
lfs e LuaCairo são plataformas cruzadas, então devem funcionar em outros sistemas (testado no WinXP Pro SP3 francês).

Fiz uma primeira versão desenhando nomes de arquivos enquanto caminhava pela árvore. Vantagem: sem sobrecarga de memória. Inconveniente: eu tenho que especificar o tamanho da imagem com antecedência, então as listagens provavelmente serão cortadas.

Então fiz essa versão, primeiro percorrendo a árvore de diretórios, armazenando-a em uma tabela Lua. Então, sabendo a quantidade de arquivos, criando a tela para caber (pelo menos na vertical) e desenhando os nomes.
Você pode alternar facilmente entre a renderização PNG e SVG. Problema com o último: Cairo o gera em baixo nível, desenhando as letras em vez de usar a capacidade de texto do SVG. Bem, pelo menos, ele garante um corte preciso, mesmo em sistemas sem a fonte. Mas os arquivos são maiores ... Não é realmente um problema se você compactá-lo depois, para ter um arquivo .svgz.
Ou não deve ser muito difícil gerar o SVG diretamente, eu usei Lua para gerar o SVG no passado.

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

Claro, você pode alterar os estilos. Eu não desenhei as linhas de conexão, não vi como necessário. Posso adicioná-los opcionalmente mais tarde.

PhiLho
fonte
3

Por que você não poderia simplesmente criar uma estrutura de arquivo no sistema de arquivos do Windows e preenchê-la com os nomes desejados, em seguida, usar um capturador de tela como o HyperSnap (ou o onipresente Alt-PrtScr) para capturar uma seção da janela do Explorer.

Fiz isso ao fazer uma 'demonstração' de um aplicativo da Internet que teria seções recolhíveis, bastando criar arquivos que se parecessem com as entradas desejadas.

O HyperSnap fornece pelo menos JPGs (provavelmente outros, mas nunca me preocupei em investigar).

Ou você poderia capturar a tela dos ícones +/- do Explorer e usá-los dentro do próprio MS Word Draw para fazer sua imagem, mas nunca consegui fazer o MS Word Draw se comportar corretamente.

paxdiablo
fonte
2

O conselho para usar o Graphviz é bom: você pode gerar o arquivo de ponto e ele fará o trabalho árduo de medir as cordas, fazer o layout, etc. Além disso, pode produzir os gráficos em vários formatos, incluindo os vetoriais.

Eu encontrei um programa Perl fazendo exatamente isso, em uma lista de e-mails, mas simplesmente não consigo encontrar de volta! Copiei o arquivo de amostra de ponto e o estudei, pois não conheço muito dessa sintaxe declarativa e queria aprender um pouco mais.

Problema: com o Graphviz mais recente, tenho erros (ou melhor, avisos, conforme o diagrama final é gerado), tanto no gráfico original como no que escrevi (à mão). Algumas pesquisas mostraram que esse erro foi encontrado em versões antigas e desapareceu nas versões mais recentes. Parece que está de volta.

Eu ainda dou o arquivo, talvez seja um ponto de partida para alguém, ou talvez seja o suficiente para as suas necessidades (claro, você ainda precisa gerá-lo).

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

Vou tentar outra direção, usando Cairo, que também é capaz de exportar vários formatos. Dá mais trabalho (calcular posições / deslocamentos) mas a estrutura é simples, não deve ser muito difícil.

PhiLho
fonte
1
Steve DeRose tem uma estrutura de arquivo de criação de Perlscript -> arquivo de ponto em derose.net/steve/utilities
claj