Elenco directory in Vai


197

Ho cercato di capire come elencare semplicemente i file e le cartelle in una singola directory in Go.

Ho trovato filepath.Walk, ma va automaticamente nelle sottodirectory, che non voglio. Tutte le altre mie ricerche non hanno migliorato nulla.

Sono sicuro che questa funzionalità esiste, ma è stato davvero difficile da trovare. Fammi sapere se qualcuno sa dove dovrei cercare. Grazie.

Risposte:


359

Puoi provare a utilizzare la funzione ReadDir nel io/ioutilpacchetto. Secondo i documenti:

ReadDir legge la directory indicata da dirname e restituisce un elenco di voci di directory ordinate.

La sezione risultante contiene os.FileInfotipi, che forniscono i metodi elencati qui . Ecco un esempio di base che elenca il nome di tutto nella directory corrente (le cartelle sono incluse ma non contrassegnate in modo speciale: puoi verificare se un elemento è una cartella usando il IsDir()metodo):

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
Se vuoi solo i nomi dei contenuti di una directory e la velocità è essenziale, nota che usare Readdirnames è ordini di grandezza più veloci (circa 20 volte più veloci per me)
SquattingSlavInTracksuit

2
@SquattingSlavInTracksuit: ho promosso il tuo commento qui come risposta, perché al momento non avevo i privilegi di commento. Se preferisci rispondere e ottenere il credito, LMK.
Jacob Kopczynski,

2
@SquattingSlavInTracksuit - questo è solo un ordine di grandezza: P
nadavvadan,

78

Ancora più semplice, utilizzare 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
Si noti cheGlob ignores file system errors such as I/O errors reading directories. The only possible returned error is ErrBadPattern, when pattern is malformed.
Jon

3
Assicurati di capire cosa fa Glob prima di usarlo. golang.org/pkg/path/filepath/#Glob
Anfernee

67

È possibile ottenere un elenco di file all'interno di una cartella sul file system utilizzando varie funzioni di libreria standard 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. Utilizzando filepath.Walk

Il path/filepathpacchetto fornisce un modo pratico per scansionare tutti i file in una directory, scansionerà automaticamente ogni sottodirectory nella directory.

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

ioutil.ReadDir legge la directory denominata per dirname e restituisce un elenco di voci della directory ordinate per nome 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. Utilizzando os.File.Readdir

Readdir legge il contenuto della directory associata al file e restituisce una porzione di fino a n valori FileInfo, come verrebbe restituito da Lstat, nell'ordine della directory. Le chiamate successive sullo stesso file produrranno ulteriori 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
}

Risultati benchmark.

punteggio di riferimento

Ulteriori dettagli su questo post del blog


3
La risposta più completa qui. Vale la pena notare che questo benchmark non prevede l'utilizzo di memoria o allocati. È possibile che le implementazioni più veloci utilizzino più memoria. È anche possibile che il numero di core della CPU sul computer del tester danneggi / aiuti i concorrenti filepath.Walk. Inoltre, filepath.Walksupporta ricorsivo decente mentre os.File.Readdire ioutil.ReadDirnon lo fanno.
Xeoncross,

24

ioutil.ReadDirè una buona scoperta, ma se fai clic e guardi la fonte vedi che chiama il metodo Readdir di os.File . Se sei d'accordo con l'ordine delle directory e non hai bisogno dell'elenco ordinato, allora questo metodo Readdir è tutto ciò di cui hai bisogno.


7

Dalla tua descrizione, ciò che probabilmente vuoi è os.Readdirnames .

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

Readdirnames legge il contenuto della directory associata al file e restituisce una porzione di fino a n nomi di file nella directory, nell'ordine della directory. Le chiamate successive sullo stesso file produrranno ulteriori nomi.

...

Se n <= 0, Readdirnames restituisce tutti i nomi dalla directory in una singola sezione.

Frammento:

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

Ringraziamo il commento di SquattingSlavInTracksuit ; Se potessi, avrei suggerito di promuovere il loro commento a una risposta.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.