Skip to content

Instantly share code, notes, and snippets.

@yougg
Created December 5, 2024 01:16
Show Gist options
  • Save yougg/6ea60fdb891afb3d843bf5673a1b1be1 to your computer and use it in GitHub Desktop.
Save yougg/6ea60fdb891afb3d843bf5673a1b1be1 to your computer and use it in GitHub Desktop.
golang simple implementation for print file tree
//go:generate go build -trimpath -ldflags "-s -w" -o tree${GOEXE} ${GOFILE}
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
)
var (
indentUnicode = `│ `
indentAscii = `| `
indentSpace = ` `
indentString string
suffixLastUnicode = `└──`
suffixLastAscii = `\__`
suffixLastString string
suffixMidUnicode = `├──`
suffixMidAscii = `|--`
suffixMidString string
)
func init() {
var ascii bool
flag.BoolVar(&ascii, "A", false, "use ASCII characters")
flag.Usage = func() {
path, err := os.Executable()
if err != nil {
fmt.Printf("get current process executable: %v", err)
os.Exit(1)
}
exe := filepath.Base(path)
fmt.Printf("Usage:\n %s [-A] <path>\n", exe)
flag.PrintDefaults()
fmt.Printf("Example:\n %s /path/to/some/dir\n %s -A ./ \n", exe, exe)
}
flag.Parse()
if ascii {
indentString = indentAscii
suffixLastString = suffixLastAscii
suffixMidString = suffixMidAscii
} else {
indentString = indentUnicode
suffixLastString = suffixLastUnicode
suffixMidString = suffixMidUnicode
}
}
func main() {
var root string
if len(os.Args) == 1 {
root = `.`
} else {
root = flag.Arg(0)
}
fmt.Println(root)
printDirectory(root, ``)
}
func printDirectory(path string, indent string) {
entries, err := os.ReadDir(path)
if err != nil {
fmt.Printf("os read path %s: %v\n", path, err)
return
}
count := len(entries)
for index, entry := range entries {
fi, err := entry.Info()
if err != nil {
continue
}
var prefix, middle, suffix string
if index+1 == count { // the last one
middle = indentSpace
suffix = suffixLastString
} else {
middle = indentString
suffix = suffixMidString
}
prefix = indent + suffix
name := entry.Name()
switch {
case (fi.Mode() & os.ModeSymlink) == os.ModeSymlink:
fullPath, err := os.Readlink(filepath.Join(path, name))
if err != nil {
fmt.Printf("%s %s: %v\n", prefix, name, err)
} else {
fmt.Println(prefix, name, `->`, fullPath)
}
case entry.IsDir():
fmt.Println(prefix, name)
printDirectory(filepath.Join(path, name), indent+middle)
default:
fmt.Println(prefix, name)
}
}
}
@yougg
Copy link
Author

yougg commented Dec 5, 2024

Build

go generate tree.go

# or
go build tree.go

Usage

tree -h
Usage:
  tree [-A] <path>
  -A    use ASCII characters
Example:
  tree /path/to/some/dir
  tree -A ./

Linux/MacOS

tree ~/code/gv
~/code/gv
├── .idea
│   ├── .gitignore
│   ├── GitLink.xml
│   ├── gv.iml
│   ├── modules.xml
│   ├── vcs.xml
│   └── workspace.xml
├── LICENSE
├── Makefile
├── README.md
├── go.mod
├── go.sum
└── main.go

Windows

tree -A D:\code\gv
D:\code\gv
|-- .idea
|   |-- .gitignore
|   |-- GitLink.xml
|   |-- gv.iml
|   |-- modules.xml
|   |-- vcs.xml
|   \__ workspace.xml
|-- LICENSE
|-- Makefile
|-- README.md
|-- go.mod
|-- go.sum
\__ main.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment