Skip to content

Instantly share code, notes, and snippets.

@igorzakhar
Last active February 3, 2018 18:25
Show Gist options
  • Save igorzakhar/31efa4052b1ae5acc57cc14fb2396fc3 to your computer and use it in GitHub Desktop.
Save igorzakhar/31efa4052b1ae5acc57cc14fb2396fc3 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
)
type TreeNode struct {
Name string
Size int64
SubNodes []TreeNode
}
func stringTree(object []TreeNode, printFiles bool) (result string) {
var spaces []bool
result += stringObjectItems(object, spaces, printFiles)
return
}
func stringObjectItems(items []TreeNode, spaces []bool, printFiles bool) (result string) {
for i, f := range items {
last := (i >= len(items)-1)
result += stringLine(f.Name, f.Size, spaces, last, printFiles)
if len(f.SubNodes) > 0 {
spacesChild := append(spaces, last)
result += stringObjectItems(f.SubNodes, spacesChild, printFiles)
}
}
return
}
func stringLine(name string, size int64, spaces []bool, last bool, printFiles bool) (result string) {
for _, space := range spaces {
if space {
result += " "
} else {
result += "│ "
}
}
indicator := "├───"
if last {
indicator = "└───"
}
if printFiles {
if size > 0 {
result += fmt.Sprintf("%s%s (%vb)\n", indicator, name, size)
} else {
result += fmt.Sprintf("%s%s (empty)\n", indicator, name)
}
} else {
result += fmt.Sprintf("%s%s\n", indicator, name)
}
return
}
func walk(dirname string) ([]TreeNode, error) {
var items []TreeNode
files, err := ioutil.ReadDir(dirname)
if err != nil {
return nil, err
}
for _, file := range files {
var child TreeNode
child.Name = file.Name()
child.Size = file.Size()
if file.IsDir() {
newNode := filepath.Join(dirname, file.Name())
child.SubNodes, err = walk(newNode)
}
items = append(items, child)
}
return items, nil
}
func dirTree(output io.Writer, directory string, printFiles bool) error {
items, err := walk(directory)
if err != nil {
return err
}
fmt.Fprintln(output, stringTree(items, printFiles))
return nil
}
func main() {
out := os.Stdout
if !(len(os.Args) == 2 || len(os.Args) == 3) {
panic("usage go run main.go . [-f]")
}
path := os.Args[1]
printFiles := len(os.Args) == 3 && os.Args[2] == "-f"
err := dirTree(out, path, printFiles)
if err != nil {
panic(err.Error())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment