Go中的列表目录

时间:2013-02-03 02:17:54

标签: go

我一直在试图弄清楚如何在Go中的单个目录中简单列出文件和文件夹。

我找到filepath.Walk,但它会自动进入子目录,这是我不想要的。我所有的其他搜索都没有变得更好。

我确信这个功能存在,但很难找到。如果有人知道我应该在哪里看,请告诉我。感谢。

6 个答案:

答案 0 :(得分:285)

您可以尝试使用io/ioutil包中的ReadDir功能。根据文档:

  

ReadDir读取dirname命名的目录,并返回已排序的目录条目列表。

生成的切片包含os.FileInfo个类型,它们提供列出的方法here。这是一个基本示例,列出了当前目录中所有内容的名称(包含文件夹但未特别标记 - 您可以使用IsDir()方法检查项目是否为文件夹):

package main

import (
    "fmt"
    "io/ioutil"
     "log"
)

func main() {
    files, err := ioutil.ReadDir("./")
    if err != nil {
        log.Fatal(err)
    }

    for _, f := range files {
            fmt.Println(f.Name())
    }
}

答案 1 :(得分:65)

更简单,使用path/filepath

package main    

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

func main() {
    files, err := filepath.Glob("*")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(files) // contains a list of all files in the current directory
}

答案 2 :(得分:43)

我们可以使用各种golang标准库函数获取文件系统文件夹中的文件列表。

  1. filepath.Walk
  2. ioutil.ReadDir
  3. os.File.Readdir
  4. 
    package main
    
    import (
        "fmt"
        "io/ioutil"
        "log"
        "os"
        "path/filepath"
    )
    
    func main() {
        var (
            root  string
            files []string
            err   error
        )
    
        root := "/home/manigandan/golang/samples"
        // filepath.Walk
        files, err = FilePathWalkDir(root)
        if err != nil {
            panic(err)
        }
        // ioutil.ReadDir
        files, err = IOReadDir(root)
        if err != nil {
            panic(err)
        }
        //os.File.Readdir
        files, err = OSReadDir(root)
        if err != nil {
            panic(err)
        }
    
        for _, file := range files {
            fmt.Println(file)
        }
    }
    
    1. 使用filepath.Walk
    2.   

      path/filepath包提供了一种扫描所有文件的便捷方法   在一个目录中,它会自动扫描每个子目录   。目录

      func FilePathWalkDir(root string) ([]string, error) {
          var files []string
          err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
              if !info.IsDir() {
                  files = append(files, path)
              }
              return nil
          })
          return files, err
      }
      
      1. 使用ioutil.ReadDir
      2.   

        ioutil.ReadDir读取dirname命名的目录并返回一个   按文件名排序的目录条目列表。

        func IOReadDir(root string) ([]string, error) {
            var files []string
            fileInfo, err := ioutil.ReadDir(root)
            if err != nil {
                return files, err
            }
        
            for _, file := range fileInfo {
                files = append(files, file.Name())
            }
            return files, nil
        }
        
        1. 使用os.File.Readdir
        2.   

          Readdir读取与file关联的目录的内容   返回最多n个FileInfo值的切片,如返回的那样   Lstat,按目录顺序。对同一文件的后续调用将会   进一步产生FileInfos。

          func OSReadDir(root string) ([]string, error) {
              var files []string
              f, err := os.Open(root)
              if err != nil {
                  return files, err
              }
              fileInfo, err := f.Readdir(-1)
              f.Close()
              if err != nil {
                  return files, err
              }
          
              for _, file := range fileInfo {
                  files = append(files, file.Name())
              }
              return files, nil
          }
          

          基准测试结果。

          benchmark score

          详细了解此Blog Post

答案 3 :(得分:21)

ioutil.ReadDir是一个不错的选择,但如果您点击并查看来源,则会看到它调用方法Readdir of os.File。如果您对目录顺序没问题并且不需要排序列表,那么您只需要这个Readdir方法。

答案 4 :(得分:9)

根据您的描述,您可能想要的是os.Readdirnames

func (f *File) Readdirnames(n int) (names []string, err error)

Readdirnames读取与文件关联的目录的内容,并按目录顺序返回目录中最多n个文件名的切片。随后对同一文件的调用将产生其他名称。

...

如果n <= 0,则Readdirnames在单个片中返回目录中的所有名称。

摘要:

file, err := os.Open(path)
if err != nil {
    return err
}
defer file.Close()
names, err := file.Readdirnames(0)
if err != nil {
    return err
}
fmt.Println(names)

贷记SquattingSlavInTracksuitcomment;如果可以的话,我建议将他们的评论提升为答案。

答案 5 :(得分:2)

Go 1.16(第2021年第1季度)将基于CL 243908提出CL 243914ReadDir functionFS interface

// An FS provides access to a hierarchical file system.
//
// The FS interface is the minimum implementation required of the file system.
// A file system may implement additional interfaces,
// such as fsutil.ReadFileFS, to provide additional or optimized functionality.
// See io/fsutil for details.
type FS interface {
    // Open opens the named file.
    //
    // When Open returns an error, it should be of type *PathError
    // with the Op field set to "open", the Path field set to name,
    // and the Err field describing the problem.
    //
    // Open should reject attempts to open names that do not satisfy
    // ValidPath(name), returning a *PathError with Err set to
    // ErrInvalid or ErrNotExist.
    Open(name string) (File, error)
}

允许使用"os: add ReadDir method for lightweight directory reading"
参见commit a4ede9f

// ReadDir reads the contents of the directory associated with the file f
// and returns a slice of DirEntry values in directory order.
// Subsequent calls on the same file will yield later DirEntry records in the directory.
//
// If n > 0, ReadDir returns at most n DirEntry records.
// In this case, if ReadDir returns an empty slice, it will return an error explaining why.
// At the end of a directory, the error is io.EOF.
//
// If n <= 0, ReadDir returns all the DirEntry records remaining in the directory.
// When it succeeds, it returns a nil error (not io.EOF).
func (f *File) ReadDir(n int) ([]DirEntry, error) 

// A DirEntry is an entry read from a directory (using the ReadDir method).
type DirEntry interface {
    // Name returns the name of the file (or subdirectory) described by the entry.
    // This name is only the final element of the path, not the entire path.
    // For example, Name would return "hello.go" not "/home/gopher/hello.go".
    Name() string
    
    // IsDir reports whether the entry describes a subdirectory.
    IsDir() bool
    
    // Type returns the type bits for the entry.
    // The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method.
    Type() os.FileMode
    
    // Info returns the FileInfo for the file or subdirectory described by the entry.
    // The returned FileInfo may be from the time of the original directory read
    // or from the time of the call to Info. If the file has been removed or renamed
    // since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist).
    // If the entry denotes a symbolic link, Info reports the information about the link itself,
    // not the link's target.
    Info() (FileInfo, error)
}

src/os/os_test.go#testReadDir()说明了其用法:

    file, err := Open(dir)
    if err != nil {
        t.Fatalf("open %q failed: %v", dir, err)
    }
    defer file.Close()
    s, err2 := file.ReadDir(-1)
    if err2 != nil {
        t.Fatalf("ReadDir %q failed: %v", dir, err2)
    }