Listenverzeichnis in Go

197

Ich habe versucht herauszufinden, wie man die Dateien und Ordner einfach in einem einzigen Verzeichnis in Go auflistet.

Ich habe gefunden filepath.Walk, aber es geht automatisch in Unterverzeichnisse, was ich nicht will. Alle meine anderen Suchanfragen haben nichts Besseres ergeben.

Ich bin mir sicher, dass diese Funktionalität vorhanden ist, aber es war wirklich schwer zu finden. Lassen Sie mich wissen, wenn jemand weiß, wo ich suchen soll. Vielen Dank.

Behram Mistree
quelle

Antworten:

359

Sie können versuchen, die ReadDir- Funktion im io/ioutilPaket zu verwenden. Gemäß den Dokumenten:

ReadDir liest das nach dirname benannte Verzeichnis und gibt eine Liste sortierter Verzeichniseinträge zurück.

Das resultierende Slice enthält os.FileInfoTypen, die die hier aufgeführten Methoden bereitstellen . Hier ist ein grundlegendes Beispiel, in dem der Name aller Elemente im aktuellen Verzeichnis aufgeführt ist (Ordner sind enthalten, aber nicht speziell gekennzeichnet - Sie können mithilfe der IsDir()Methode überprüfen, ob ein Element ein Ordner ist ):

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
quelle
7
Wenn Sie nur die Namen der Inhalte eines Verzeichnisses möchten und die Geschwindigkeit von entscheidender Bedeutung ist, beachten Sie, dass die Verwendung von Readdirnames um Größenordnungen schneller ist (für mich etwa 20-mal schneller)
SquattingSlavInTracksuit
2
@SquattingSlavInTracksuit: Ich habe Ihren Kommentar hier zu einer Antwort befördert, da ich zu diesem Zeitpunkt keine Kommentarberechtigungen hatte. Wenn Sie es lieber beantworten und die Gutschrift erhalten möchten, LMK.
Jacob Kopczynski
2
@SquattingSlavInTracksuit - das ist nur eine Größenordnung: P
nadavvadan
78

Verwenden Sie noch einfacher 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
quelle
8
Beachten Sie, dassGlob ignores file system errors such as I/O errors reading directories. The only possible returned error is ErrBadPattern, when pattern is malformed.
Jon
3
Stellen Sie sicher, dass Sie verstehen, was Glob tut, bevor Sie es verwenden. golang.org/pkg/path/filepath/#Glob
Anfernee
65

Wir können eine Liste von Dateien in einem Ordner im Dateisystem mit verschiedenen Golang-Standardbibliotheksfunktionen abrufen.

  1. Dateipfad.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. Verwenden von filepath.Walk

Das path/filepathPaket bietet eine praktische Möglichkeit, alle Dateien in einem Verzeichnis zu scannen. Es scannt automatisch alle Unterverzeichnisse im Verzeichnis.

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. Verwenden von ioutil.ReadDir

ioutil.ReadDir liest das nach dirname benannte Verzeichnis und gibt eine nach Dateinamen sortierte Liste der Verzeichniseinträge zurück.

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

Readdir liest den Inhalt des mit der Datei verknüpften Verzeichnisses und gibt einen Slice mit bis zu n FileInfo-Werten in Verzeichnisreihenfolge zurück, wie dies von Lstat zurückgegeben würde. Nachfolgende Aufrufe derselben Datei führen zu weiteren 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-Ergebnisse.

Benchmark-Score

Erfahren Sie mehr über diesen Blog-Beitrag

Manigandand
quelle
3
Die vollständigste Antwort hier. Es ist erwähnenswert, dass von diesem Benchmark keine Speichernutzung oder Zuweisungen gemeldet werden. Es ist möglich, dass die schnelleren Implementierungen mehr Speicher belegen. Es ist auch möglich, dass die Anzahl der CPU-Kerne auf dem Computer des Testers die gleichzeitige Verletzung beeinträchtigt filepath.Walk. Darüber hinaus filepath.Walkunterstützt rekursive anständige während os.File.Readdirund ioutil.ReadDirnicht.
Xeoncross
24

ioutil.ReadDirist ein guter Fund, aber wenn Sie auf die Quelle klicken und sie sich ansehen, sehen Sie, dass sie die Methode Readdir von os.File aufruft . Wenn Sie mit der Verzeichnisreihenfolge einverstanden sind und die Liste nicht sortiert werden müssen, ist diese Readdir-Methode alles, was Sie benötigen.

Sonia
quelle
7

Nach Ihrer Beschreibung möchten Sie wahrscheinlich os.Readdirnames .

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

Readdirnames liest den Inhalt des mit der Datei verknüpften Verzeichnisses und gibt einen Slice mit bis zu n Dateinamen im Verzeichnis in Verzeichnisreihenfolge zurück. Nachfolgende Aufrufe derselben Datei ergeben weitere Namen.

...

Wenn n <= 0 ist, gibt Readdirnames alle Namen aus dem Verzeichnis in einem einzelnen Slice zurück.

Snippet:

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

Dank an den Kommentar von SquattingSlavInTracksuit ; Ich hätte vorgeschlagen, ihren Kommentar zu einer Antwort zu machen, wenn ich könnte.

Jacob Kopczynski
quelle