Daftar direktori di Go

197

Saya sudah mencoba mencari cara bagaimana daftar file dan folder dalam satu direktori di Go.

Saya telah menemukan filepath.Walk, tetapi masuk ke dalam sub-direktori secara otomatis, yang tidak saya inginkan. Semua pencarian saya yang lain belum menghasilkan hal yang lebih baik.

Saya yakin bahwa fungsi ini ada, tetapi sangat sulit ditemukan. Beri tahu saya jika ada yang tahu di mana saya harus mencari. Terima kasih.

Behram Mistree
sumber

Jawaban:

359

Anda dapat mencoba menggunakan fungsi ReadDir dalam io/ioutilpaket. Per dokumen:

ReadDir membaca direktori bernama dengan dirname dan mengembalikan daftar entri direktori yang diurutkan.

Irisan yang dihasilkan berisi os.FileInfotipe, yang menyediakan metode yang tercantum di sini . Berikut ini adalah contoh dasar yang mencantumkan nama semua yang ada di direktori saat ini (folder disertakan tetapi tidak ditandai secara khusus - Anda dapat memeriksa apakah suatu item adalah folder dengan menggunakan IsDir()metode ini):

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())
    }
}
RocketDonkey
sumber
7
Jika Anda hanya ingin nama - nama isi direktori dan kecepatan adalah esensi, perhatikan bahwa menggunakan Readdirnames adalah urutan besarnya lebih cepat (sekitar 20x lebih cepat untuk saya)
SquattingSlavInTracksuit
2
@SquattingSlavInTracksuit: Saya mempromosikan komentar Anda di sini sebagai jawaban, karena saya tidak memiliki hak komentar pada saat itu. Jika Anda lebih suka menjawabnya dan mendapatkan kredit, LMK.
Jacob Kopczynski
2
@SquattingSlavInTracksuit - itu hanya satu urutan besarnya: P
nadavvadan
78

Lebih sederhana, gunakan 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
}
Fatih Arslan
sumber
8
Perhatikan bahwaGlob ignores file system errors such as I/O errors reading directories. The only possible returned error is ErrBadPattern, when pattern is malformed.
Jon
3
Pastikan untuk memahami apa yang dilakukan Glob sebelum menggunakannya. golang.org/pkg/path/filepath/#Glob
Anfernee
67

Kita bisa mendapatkan daftar file di dalam folder pada sistem file menggunakan berbagai fungsi pustaka standar golang.

  1. filepath.Walk
  2. ioutil.ReadDir
  3. o.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. Menggunakan filepath.Walk

The path/filepathpaket menyediakan cara yang berguna untuk memindai semua file dalam direktori, maka secara otomatis akan memindai setiap sub-direktori dalam direktori.

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. Menggunakan ioutil.ReadDir

ioutil.ReadDir membaca direktori bernama dengan dirname dan mengembalikan daftar entri direktori yang diurutkan berdasarkan nama file.

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. Menggunakan os.File.Readdir

Readdir membaca isi direktori yang terkait dengan file dan mengembalikan sepotong hingga n nilai FileInfo, seperti yang akan dikembalikan oleh Lstat, dalam urutan direktori. Panggilan selanjutnya pada file yang sama akan menghasilkan FileInfos lebih lanjut.

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
}

Hasil benchmark.

skor benchmark

Mendapatkan rincian lebih lanjut tentang ini Blog Post

manigandand
sumber
3
Jawaban paling lengkap di sini. Perlu dicatat bahwa tidak ada penggunaan memori atau allocs yang dilaporkan oleh tolok ukur ini. Ada kemungkinan implementasi yang lebih cepat menggunakan lebih banyak memori. Mungkin juga bahwa jumlah inti CPU pada komputer penguji sakit / membantu bersamaan filepath.Walk. Selanjutnya, filepath.Walkmendukung rekursif yang layak sementara os.File.Readdirdan ioutil.ReadDirtidak.
Xeoncross
24

ioutil.ReadDiradalah menemukan yang baik, tetapi jika Anda mengklik dan melihat sumber Anda melihat bahwa itu memanggil metode Readdir dari os.File . Jika Anda baik-baik saja dengan urutan direktori dan tidak perlu daftar diurutkan, maka metode Readdir ini adalah semua yang Anda butuhkan.

Sonia
sumber
7

Dari deskripsi Anda, apa yang mungkin Anda inginkan adalah os.Readdirnames .

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

Readdirnames membaca konten direktori yang terkait dengan file dan mengembalikan sepotong hingga n nama file dalam direktori, dalam urutan direktori. Panggilan selanjutnya pada file yang sama akan menghasilkan nama lebih lanjut.

...

Jika n <= 0, Readdirnames mengembalikan semua nama dari direktori dalam satu irisan.

Potongan:

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

Kredit untuk SquattingSlavInTracksuit 's komentar ; Saya menyarankan untuk mempromosikan komentar mereka ke jawaban jika saya bisa.

Jacob Kopczynski
sumber