使用go语言提取目录层次结构 [英] extracting directory hierarchy using go language

查看:171
本文介绍了使用go语言提取目录层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用go语言将文件夹的目录层次结构提取到数据结构中。 filepath.Walk 似乎是要走的路,但我迄今所能做的只是打印文件和文件夹的名称。以下是我用的:

  func main(){
visit:= func(path string,info os .fileInfo,err错误)错误{
if info.IsDir(){
fmt.Println(dir:,path)
} else {
fmt.Println( file:,path)
}
return nil
}

err:= filepath.Walk(./,visit)
if err != nil {
log.Fatal(err)
}
}



  dir:folder1 
file:folder1 / file1.txt
file:folder1 / file2.txt
file:folder1 / file3.txt
file:folder1 / file4.txt
dir:folder1 / folder2
file:folder1 / folder2 /file5.txt
文件:folder1 / folder2 / file6.txt
文件:folder1 / folder2 / file7.txt
文件:folder1 / folder2 / file8.txt
文件:folder1 /folder2/file9.txt

对于树形结构,我曾考虑过使用类似于

 类型文件struct {
名称字符串
内容字符串
}

键入文件夹结构{
名称字符串
文件[]文件
文件夹[]文件夹
}

,但当然欢迎提供任何建议。



如何将这个转换为树形结构?有没有一种更简单的方法来做到这一点? 标准库。

树结构适用于递归方法。我在文件和文件夹类型中定义了 addFile addFolder 方法。从根文件夹开始,然后可以在Walk中调用这些方法。如果你得到一个/ b / c,我们将调用 root.addFile(a,b,c) a.addFile(b, c) b.addFile(c)



我也改变了文件夹。文件夹到地图,因为filepath.Walk总是给我们完整的路径,所以我们可以拆分它们并在文件夹地图中查找它们的组件。



这里有一些快速和脏代码可能有错误,并且不会执行完整的错误检查。它只适用于当前目录,但应该很容易修复。



我还在Folder上添加了一个String()方法,它被编译器识别并将在打印出类型的实例时使用。

  package main 

import(
log
os
路径/文件路径
字符串


类型文件struct {
名称字符串


类型文件夹结构{
名称字符串
文件[]文件
文件夹映射[字符串] *文件夹
}

func newFolder(name string)*文件夹{
return& Folder {name,[] File {},make(map [string] * Folder)}
}

func(f * Folder)getFolder(name string)*文件夹{
if nextF,ok:= f.Folders [name]; ok {
return nextF
} else {
log.Fatalf(Expected nested folder%v in%v \\\
,name,f.Name)
}
return& Folder {} //不会发生
}

func(f * Folder)addFolder(path [] string){
for i,segment:= range路径{
if i == len(path)-1 {//最后一段==新文件夹
f.Folders [segment] = newFolder(segment)
} else {
f.getFolder(segment).addFolder(path [1:])
}
}
}

func(f * Folder)addFile(path []字符串){
for i,segment:= range path {
if i == len(path)-1 {//最后一段==文件
f.Files = append(f。文件{file})
} else {
f.getFolder(segment).addFile(path [1:])
return
}
}

$ b $ func(f * Folder)String()string {
var str string
for _,file:= range f.Files {
str + = f .Name + string(filepath.Separator)+ file.Name +\\\

}
for _,folder:= range f.Folders {
str + = folder.String( )
}
return str
}

func main(){
startPath:=。
rootFolder:= newFolder(startPath)

visit:= func(path string,info os.FileInfo,err error)error {
segments:= strings.Split(path, string(filepath.Separator))
if info.IsDir(){
if path!= startPath {
rootFolder.addFolder(segments)
}
} else {
rootFolder.addFile(segments)
}
return nil
}

err:= filepath.Walk(startPath,visit)
if err!= nil {
log.Fatal(err)
}

log.Printf(%v \ n,rootFolder)
}


I'm trying to extract the directory hierarchy of a folder into a datastructure in go language. filepath.Walk seems to be the way to go but all I can do so far is to print the names of files and folders. Here's what I'm using:

func main() {
    visit := func(path string, info os.FileInfo, err error) error {
        if info.IsDir() {
            fmt.Println("dir:  ", path)
        } else {
            fmt.Println("file: ", path)
        }
        return nil
    }

    err := filepath.Walk("./", visit)
    if err != nil {
        log.Fatal(err)
    }
}

this prints the names of folders like:

dir:   folder1
file:  folder1/file1.txt
file:  folder1/file2.txt
file:  folder1/file3.txt
file:  folder1/file4.txt
dir:   folder1/folder2
file:  folder1/folder2/file5.txt
file:  folder1/folder2/file6.txt
file:  folder1/folder2/file7.txt
file:  folder1/folder2/file8.txt
file:  folder1/folder2/file9.txt

for tree structure I thought about using something like:

type File struct {
    Name string
    Content string
}

type Folder struct {
    Name    string
    Files   []File
    Folders []Folder
}

but of course any suggestions are welcomed.

How can I convert this to a tree structure in go? Is there an easier way to do this?

解决方案

AFAIK there is nothing ready-made for this in the Go standard lib.

Tree structures lend themselves well to a recursive approach. I defined addFile and addFolder methods on your File and Folder types. Starting with a root folder, you can then call these methods in Walk. If you get a/b/c, we'll be calling root.addFile(a, b, c), a.addFile(b, c), b.addFile(c).

I also changed Folder.Folders to a map, because filepath.Walk always gives us full paths, so we can split those and look up their components in the folder map.

Here is some quick and dirty code that probably has bugs and doesn't do full error checking. It only works for the current directory, but that should be easy to fix.

I also added a String() method on Folder, which is recognized by the compiler and will be used when printing out instances of the type.

package main

import (
    "log"
    "os"
    "path/filepath"
    "strings"
)

type File struct {
    Name string
}

type Folder struct {
    Name    string
    Files   []File
    Folders map[string]*Folder
}

func newFolder(name string) *Folder {
    return &Folder{name, []File{}, make(map[string]*Folder)}
}

func (f *Folder) getFolder(name string) *Folder {
    if nextF, ok := f.Folders[name]; ok {
        return nextF
    } else {
        log.Fatalf("Expected nested folder %v in %v\n", name, f.Name)
    }
    return &Folder{} // cannot happen
}

func (f *Folder) addFolder(path []string) {
    for i, segment := range path {
        if i == len(path)-1 { // last segment == new folder
            f.Folders[segment] = newFolder(segment)
        } else {
            f.getFolder(segment).addFolder(path[1:])
        }
    }
}

func (f *Folder) addFile(path []string) {
    for i, segment := range path {
        if i == len(path)-1 { // last segment == file
            f.Files = append(f.Files, File{segment})
        } else {
            f.getFolder(segment).addFile(path[1:])
            return
        }
    }
}

func (f *Folder) String() string {
    var str string
    for _, file := range f.Files {
        str += f.Name + string(filepath.Separator) + file.Name + "\n"
    }
    for _, folder := range f.Folders {
        str += folder.String()
    }
    return str
}

func main() {
    startPath := "."
    rootFolder := newFolder(startPath)

    visit := func(path string, info os.FileInfo, err error) error {
        segments := strings.Split(path, string(filepath.Separator))
        if info.IsDir() {
            if path != startPath {
                rootFolder.addFolder(segments)
            }
        } else {
            rootFolder.addFile(segments)
        }
        return nil
    }

    err := filepath.Walk(startPath, visit)
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("%v\n", rootFolder)
}

这篇关于使用go语言提取目录层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆