go file dir walk


原文链接: go file dir walk

递归遍历

	// We use a counting semaphore to limit
	// the number of parallel calls to ReadDir.
	sema := make(chan bool, 20)

func allPackages(ctxt *build.Context, sema chan bool, root string, ch chan<- item) {
	root = filepath.Clean(root) + string(os.PathSeparator)

	var wg sync.WaitGroup

	var walkDir func(dir string)
	walkDir = func(dir string) {
		// Avoid .foo, _foo, and testdata directory trees.
		base := filepath.Base(dir)
		if base == "" || base[0] == '.' || base[0] == '_' || base == "testdata" {
			return
		}
		for _, ignoredFolder := range ignoreFolders {
			if base == ignoredFolder {
				return
			}
		}

		pkg := filepath.ToSlash(strings.TrimPrefix(dir, root))

		// Prune search if we encounter any of these import paths.
		switch pkg {
		case "builtin":
			return
		}

		sema <- true
		files, err := ioutil.ReadDir(dir)
		<-sema

		if err == nil {
			ch <- item{pkg, err}
		}
		for _, fi := range files {
			fi := fi
			if fi.IsDir() {
				wg.Add(1)
				go func() {
					walkDir(filepath.Join(dir, fi.Name()))
					wg.Done()
				}()
			}
		}
	}

	walkDir(root)
	wg.Wait()
}
func search(ctx context.Context, root string, pattern string) ([]string, error) {
	g, ctx := errgroup.WithContext(ctx)
	paths := make(chan string, 100)
	// get all the paths

	g.Go(func() error {
		defer close(paths)

		return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if !info.Mode().IsRegular() {
				return nil
			}
			// if !info.IsDir() && !strings.HasSuffix(info.Name(), ".go") {
			// 	return nil
			// }

			select {
			case paths <- path:
			case <-ctx.Done():
				return ctx.Err()
			}
			return nil
		})

	})

	c := make(chan string, 100)
	for path := range paths {
		p := path
		g.Go(func() error {
			data, err := ioutil.ReadFile(p)
			if err != nil {
				return err
			}
			if !bytes.Contains(data, []byte(pattern)) {
				return nil
			}
			select {
			case c <- p:
				println(p)
			case <-ctx.Done():
				return ctx.Err()
			}
			return nil
		})
	}
	go func() {
		g.Wait()
		close(c)
	}()

	var m []string
	for r := range c {
		m = append(m, r)
	}
	return m, g.Wait()
}

GoLang 遍历目录,一个常用的功能。

package main
import (
    "path/filepath"
    "os"
    "fmt"
    "flag"
)

func getFilelist(path string) {
        err := filepath.Walk(path, func(path string, f os.FileInfo, err error) error {
                if ( f == nil ) {return err}
                if f.IsDir() {return nil}
                println(path)
                return nil
        })
        if err != nil {
                fmt.Printf("filepath.Walk() returned %v\n", err)
        }
}

func main(){
        flag.Parse()
        root := flag.Arg(0)
        getFilelist(root)
}

下面这个只列出当前文件夹下的文件:

package main

import "io/ioutil"

func listAll(path string) {
    files, _ := ioutil.ReadDir(path)
    for _, fi := range files {
        if fi.IsDir() {
            //listAll(path + "/" + fi.Name())
            println(path + "/" + fi.Name())
        } else {
            println(path + "/" + fi.Name())
        }
    }
}
func main() {
    listAll(".")
}

另一个版本:

package main

import (
    "flag"
    "fmt"
    "os"
    "path/filepath"
)

func walkpath(path string, f os.FileInfo, err error) error {
    fmt.Printf("%s with %d bytes\n", path, f.Size())
    return nil
}

func main() {
    flag.Parse()
    root := flag.Arg(0) // 1st argument is the directory location
    fmt.Println(root)
    filepath.Walk("./", walkpath)
}

版本 4:

package main

import (
    "fmt"
    "os"
    "path/filepath"
)

func main() ([]string, error) {
    searchDir := "c:/path/to/dir"

    fileList := []string{}
    err := filepath.Walk(searchDir, func(path string, f os.FileInfo, err error) error {
        fileList = append(fileList, path)
        return nil
    })

    for _, file := range fileList {
        fmt.Println(file)
    }
}
`