Danh sách thư mục trong Go


197

Tôi đã cố gắng tìm ra cách đơn giản là liệt kê các tệp và thư mục trong một thư mục trong Go.

Tôi đã tìm thấy filepath.Walk, nhưng nó tự động đi vào các thư mục con mà tôi không muốn. Tất cả các tìm kiếm khác của tôi đã không làm mọi thứ tốt hơn.

Tôi chắc chắn rằng chức năng này tồn tại, nhưng nó thực sự rất khó tìm. Hãy cho tôi biết nếu có ai biết tôi nên tìm ở đâu. Cảm ơn.

Câu trả lời:


359

Bạn có thể thử sử dụng chức năng ReadDir trong io/ioutilgói. Theo các tài liệu:

ReadDir đọc thư mục được đặt tên bởi dirname và trả về một danh sách các mục nhập thư mục được sắp xếp.

Các lát kết quả chứa os.FileInfocác loại, cung cấp các phương thức được liệt kê ở đây . Dưới đây là một ví dụ cơ bản liệt kê tên của mọi thứ trong thư mục hiện tại (các thư mục được bao gồm nhưng không được đánh dấu đặc biệt - bạn có thể kiểm tra xem một mục có phải là thư mục hay không bằng cách sử dụng IsDir()phương thức):

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())
    }
}

7
Nếu bạn chỉ muốn tên của nội dung của một thư mục và tốc độ là điều cốt yếu, hãy lưu ý rằng sử dụng Readdirnamescác đơn đặt hàng có cường độ nhanh hơn (nhanh hơn khoảng 20 lần đối với tôi)
SquattedSlavInTracksuit

2
@SquattedSlavInTracksuit: Tôi đã quảng cáo nhận xét của bạn ở đây để trả lời, vì lúc đó tôi không có đặc quyền nhận xét. Nếu bạn muốn trả lời nó và nhận được tín dụng, LMK.
Jacob Kopczynski

2
@SquattedSlavInTracksuit - đó chỉ là một thứ tự cường độ: P
nadavvadan

78

Thậm chí đơn giản hơn, sử dụng 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
}

8
Lưu ý rằngGlob ignores file system errors such as I/O errors reading directories. The only possible returned error is ErrBadPattern, when pattern is malformed.
Jon

3
Hãy chắc chắn để hiểu những gì Glob làm trước khi sử dụng nó. golang.org/pkg/path/filepath/#Glob
Anfernee

66

Chúng ta có thể lấy danh sách các tệp trong một thư mục trên hệ thống tệp bằng các hàm thư viện chuẩn golang khác nhau.

  1. filepath.Walk
  2. ioutil.ReadDir
  3. os.File.Readdir

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. Sử dụng filepath.Walk

Các path/filepathgói cung cấp một cách tiện dụng để quét tất cả các tập tin trong một thư mục, nó sẽ tự động quét từng thư mục con trong thư mục.

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. Sử dụng ioutil.ReadDir

ioutil.ReadDir đọc thư mục được đặt tên bởi dirname và trả về một danh sách các mục nhập thư mục được sắp xếp theo tên tệp.

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. Sử dụng os.File.Readdir

Readdir đọc nội dung của thư mục được liên kết với tệp và trả về một lát lên đến n giá trị FileInfo, như được trả về bởi Lstat, theo thứ tự thư mục. Các cuộc gọi tiếp theo trên cùng một tệp sẽ mang lại FileInfos hơn nữa.

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
}

Kết quả điểm chuẩn.

điểm chuẩn

Nhận thêm thông tin chi tiết về bài đăng trên blog này


3
Câu trả lời đầy đủ nhất ở đây. Điều đáng chú ý là không có việc sử dụng bộ nhớ hoặc allocs được báo cáo bởi điểm chuẩn này. Có thể việc triển khai nhanh hơn sử dụng nhiều bộ nhớ hơn. Cũng có thể số lượng lõi CPU trên máy tính của người kiểm tra bị tổn thương / giúp đồng thời filepath.Walk. Hơn nữa, filepath.Walkhỗ trợ đệ quy đàng hoàng trong khi os.File.Readdirioutil.ReadDirkhông.
Xeoncross

24

ioutil.ReadDirlà một tìm kiếm tốt, nhưng nếu bạn nhấp và nhìn vào nguồn bạn thấy rằng nó gọi phương thức Readdir của os.File . Nếu bạn ổn với thứ tự thư mục và không cần danh sách được sắp xếp, thì phương thức Readdir này là tất cả những gì bạn cần.


7

Từ mô tả của bạn, những gì bạn có thể muốn là os.Readdirnames .

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

Readdirnames đọc nội dung của thư mục được liên kết với tệp và trả về một lát lên đến n tên của các tệp trong thư mục, theo thứ tự thư mục. Các cuộc gọi tiếp theo trên cùng một tệp sẽ mang lại thêm tên.

...

Nếu n <= 0, Readdirnames trả về tất cả các tên từ thư mục trong một lát.

Đoạn trích:

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

Tín dụng cho bình luận của SquattedSlavInTracksuit ; Tôi đã đề nghị thúc đẩy bình luận của họ để trả lời nếu tôi có thể.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.