Liste des répertoires dans Go

197

J'ai essayé de comprendre comment répertorier simplement les fichiers et dossiers dans 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 amélioré 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.

Behram Mistree
la source

Réponses:

359

Vous pouvez essayer d'utiliser la fonction ReadDir dans le io/ioutilpackage. Selon les documents:

ReadDir lit le répertoire nommé par dirname et renvoie une liste des entrées de répertoire triées.

La tranche résultante contient des os.FileInfotypes qui fournissent les méthodes répertoriées ici . Voici un exemple de base qui répertorie le nom de tout dans le répertoire actuel (les dossiers sont inclus mais pas spécialement marqués - vous pouvez vérifier si un élément est un dossier en utilisant la 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())
    }
}
RocketDonkey
la source
7
Si vous ne souhaitez que les noms du contenu d'un répertoire et la vitesse est de l' essence, notez que l' utilisation Readdirnames est des ordres de grandeur plus rapide (environ 20x plus rapide pour moi)
SquattingSlavInTracksuit
2
@SquattingSlavInTracksuit: J'ai promu votre commentaire ici en réponse, car je n'avais pas de privilèges de commentaire à l'époque. Si vous préférez y répondre et obtenir le crédit, LMK.
Jacob Kopczynski
2
@SquattingSlavInTracksuit - ce n'est qu'un ordre de grandeur: P
nadavvadan
78

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
}
Fatih Arslan
la source
8
Notez queGlob ignores file system errors such as I/O errors reading directories. The only possible returned error is ErrBadPattern, when pattern is malformed.
Jon
3
Assurez-vous de comprendre ce que fait Glob avant de l'utiliser. golang.org/pkg/path/filepath/#Glob
Anfernee
67

Nous pouvons obtenir une liste de fichiers dans un dossier sur le système de fichiers en utilisant diverses fonctions de 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)
    }
}
  1. Utilisation de filepath.Walk

Le path/filepathpackage fournit un moyen pratique d'analyser tous les fichiers d'un répertoire, il analysera automatiquement chaque sous-répertoire du 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 d'ioutil.ReadDir

ioutil.ReadDir lit le répertoire nommé par dirname et renvoie une 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 d'os.File.Readdir

Readdir lit le contenu du répertoire associé au fichier et retourne une tranche de jusqu'à n valeurs FileInfo, comme cela serait retourné par Lstat, dans l'ordre du répertoire. Les appels ultérieurs sur le même fichier donneront d'autres 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
}

Résultats de référence.

score de référence

Obtenez plus de détails sur ce billet de blog

manigandand
la source
3
La réponse la plus complète ici. Il convient de noter qu'il n'y a pas d'utilisation de mémoire ou d'allocations signalées par cette référence. Il est possible que les implémentations plus rapides utilisent plus de mémoire. Il est également possible que le nombre de cœurs de processeur sur l'ordinateur du testeur blesse / aide le concurrent filepath.Walk. En outre, filepath.Walkprend en charge récursif décent tandis que os.File.Readdiret ioutil.ReadDirnon.
Xeoncross
24

ioutil.ReadDirest une bonne trouvaille, mais si vous cliquez et regardez la source, vous voyez qu'elle appelle la méthode Readdir d'os.File . Si vous êtes d'accord avec l'ordre des répertoires et n'avez pas besoin de trier la liste, alors cette méthode Readdir est tout ce dont vous avez besoin.

Sonia
la source
7

D'après votre description, ce que vous voulez probablement, c'est os.Readdirnames .

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

Readdirnames lit le contenu du répertoire associé au fichier et renvoie une tranche de jusqu'à n noms de fichiers dans le répertoire, dans l'ordre du répertoire. Les appels ultérieurs sur le même fichier donneront d'autres noms.

...

Si n <= 0, Readdirnames renvoie tous les noms du répertoire en une seule tranche.

Fragment:

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

Crédit SquattingSlavInTracksuit de » commentaire ; J'aurais suggéré de faire de leur commentaire une réponse si je le pouvais.

Jacob Kopczynski
la source