310 votes

Répertoire de liste en Go

J'ai essayé de trouver comment lister simplement les fichiers et les dossiers d'un seul répertoire dans Go.

J'ai trouvé filepath.Walk mais il va automatiquement dans les sous-répertoires, ce que je ne veux pas. Toutes mes autres recherches n'ont rien donné de mieux.

Je suis sûr que cette fonctionnalité existe, mais elle a été très difficile à trouver. Faites-moi savoir si quelqu'un sait où je dois chercher. Merci.

497voto

RocketDonkey Points 16205

Vous pouvez essayer d'utiliser le ReadDir dans le io/ioutil paquet. Selon la documentation :

ReadDir lit le répertoire nommé par dirname et retourne une liste d'entrées de répertoire triées.

La tranche résultante contient os.FileInfo qui fournissent les méthodes énumérées ci-dessous aquí . Voici un exemple de base qui liste le nom de tout ce qui se trouve dans le répertoire actuel (les dossiers sont inclus mais ne sont pas spécialement marqués - vous pouvez vérifier si un élément est un dossier en utilisant la fonction IsDir() méthode) :

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

116voto

manigandand Points 1346

Nous pouvons obtenir une liste de fichiers à l'intérieur d'un dossier sur le système de fichiers en utilisant diverses fonctions de la bibliothèque standard de Golang.

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

    }

  4. Utilisation de filepath.Walk

El path/filepath fournit un moyen pratique d'analyser tous les fichiers dans un répertoire, il analysera automatiquement tous les sous-répertoires dans le répertoire.

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. Utilisation de ioutil.ReadDir

ioutil.ReadDir lit le répertoire nommé par dirname et retourne un fichier liste des entrées du répertoire triées par nom de fichier.

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

Readdir lit le contenu du répertoire associé au fichier et retourne une tranche de jusqu'à n valeurs FileInfo, comme celles qui seraient retournées par Lstat, dans l'ordre du répertoire. Les appels ultérieurs sur le même fichier produiront d'autres FileInfo.

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
}

Résultats de l'évaluation comparative.

benchmark score

Plus de détails sur ce sujet Blog Post

82voto

Fatih Arslan Points 2759

Encore plus simple, utilisez 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
}

28voto

VonC Points 414372

À partir de Go 1.16, vous pouvez utiliser la fonction os.ReadDir función.

func ReadDir(name string) ([]DirEntry, error)

Elle lit un répertoire donné et renvoie un DirEntry tranche qui contient les entrées du répertoire triées par nom de fichier.

Il s'agit d'une fonction optimiste, de sorte que, lorsqu'une erreur se produit lors de la lecture des entrées du répertoire, elle essaie de vous retourner une tranche avec les noms de fichiers jusqu'au point précédant l'erreur.

package main

import (
    "fmt"
    "log"
    "os"
)

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

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

Intéressant : Go 1.17 (Q3 2021) comprend fs.FileInfoToDirEntry() :

func FileInfoToDirEntry(info FileInfo) DirEntry

FileInfoToDirEntry renvoie un DirEntry qui renvoie des informations provenant de info .
Si info est nul, FileInfoToDirEntry retourne nil.


Contexte

Go 1.16 (Q1 2021) proposera, avec CL 243908 y CL 243914 le ReadDir fonction sur la base de la FS 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)
}

Cela permet "os : ajouter ReadDir méthode pour la lecture légère des répertoires " :
Voir commettre 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() illustre son utilisation :

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

Ben Hoyt souligne dans les commentaires à emporter 1.16 os.ReadDir :

os.ReadDir(path string) ([]os.DirEntry, error) que vous pourrez appeler directement sans l'aide de l'outil de gestion de l'information. Open danse.
Donc vous pouvez probablement raccourcir ça à juste os.ReadDir car c'est la fonction concrète que la plupart des gens appelleront.

Voir commettre 3d913a9 (Déc. 2020) :

os : add ReadFile , WriteFile , CreateTemp (a été TempFile ), MkdirTemp (a été TempDir ) de io/ioutil

io/ioutil était une collection d'aides mal définies.

Proposition n° 40025 a déplacé les aides génériques d'E/S vers io. Ce CL pour proposition #42026 déplace les aides spécifiques au système d'exploitation vers os , rendant l'ensemble du io/ioutil paquet déprécié.

os.ReadDir renvoie à []DirEntry contrairement à ioutil.ReadDir 's []FileInfo .
(Fournir une aide qui renvoie []DirEntry est l'une des principales motivations de ce changement).

23voto

Sonia Points 6077

ioutil.ReadDir est une bonne trouvaille, mais si vous cliquez et regardez la source, vous voyez qu'elle appelle la méthode Readdir de os.File . Si l'ordre des répertoires vous convient et que vous n'avez pas besoin de trier la liste, la méthode Readdir est tout ce dont vous avez besoin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X