Listar directorio en Ir

197

He estado tratando de descubrir cómo simplemente enumerar los archivos y carpetas en un solo directorio en Go.

Lo he encontrado filepath.Walk, pero entra en subdirectorios automáticamente, lo que no quiero. Todas mis otras búsquedas no han mejorado nada.

Estoy seguro de que esta funcionalidad existe, pero ha sido realmente difícil de encontrar. Avísame si alguien sabe dónde debo mirar. Gracias.

Behram Mistree
fuente

Respuestas:

359

Puede intentar usar la función ReadDir en el io/ioutilpaquete. Por los documentos:

ReadDir lee el directorio nombrado por dirname y devuelve una lista de entradas de directorio ordenadas.

El segmento resultante contiene os.FileInfotipos, que proporcionan los métodos enumerados aquí . Aquí hay un ejemplo básico que enumera el nombre de todo en el directorio actual (las carpetas están incluidas pero no están especialmente marcadas; puede verificar si un elemento es una carpeta utilizando el IsDir()método):

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())
    }
}
CoheteDonkey
fuente
77
Si solo desea los nombres de los contenidos de un directorio y la velocidad es esencial, tenga en cuenta que usar Readdirnames es un orden de magnitud más rápido (alrededor de 20 veces más rápido para mí)
SquattingSlavInTracksuit
2
@SquattingSlavInTracksuit: promocioné su comentario aquí a una respuesta, porque no tenía privilegios de comentario en ese momento. Si prefiere responderlo y obtener el crédito, LMK.
Jacob Kopczynski
2
@SquattingSlavInTracksuit - ese es solo un orden de magnitud: P
nadavvadan
78

Aún más simple, use 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
fuente
8
Tenga en cuenta 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
Asegúrese de comprender qué hace Glob antes de usarlo. golang.org/pkg/path/filepath/#Glob
Anfernee
67

Podemos obtener una lista de archivos dentro de una carpeta en el sistema de archivos usando varias funciones de biblioteca estándar 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. Usando filepath.Walk

El path/filepathpaquete proporciona una forma práctica de escanear todos los archivos en un directorio, escaneará automáticamente cada subdirectorio en el directorio.

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

ioutil.ReadDir lee el directorio nombrado por dirname y devuelve una lista de entradas de directorio ordenadas por nombre de archivo.

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

Readdir lee el contenido del directorio asociado con el archivo y devuelve una porción de hasta n valores FileInfo, como lo devolvería Lstat, en orden de directorio. Las llamadas posteriores en el mismo archivo generarán más 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
}

Resultados de referencia.

puntaje de referencia

Obtenga más detalles sobre esta publicación de blog

Manigandand
fuente
3
La respuesta más completa aquí. Vale la pena señalar que no hay uso de memoria o asignaciones informadas por este punto de referencia. Es posible que las implementaciones más rápidas usen más memoria. También es posible que el número de núcleos de CPU en la computadora del probador perjudique / ayude al concurrente filepath.Walk. Además, filepath.Walkadmite recursivos decentes mientras que os.File.Readdiry ioutil.ReadDirno.
Xeoncross
24

ioutil.ReadDires un buen hallazgo, pero si hace clic y mira la fuente verá que llama al método Readdir de os.File . Si está de acuerdo con el orden del directorio y no necesita ordenar la lista, entonces este método Readdir es todo lo que necesita.

Sonia
fuente
7

De tu descripción, lo que probablemente quieras es os.Readdirnames .

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

Readdirnames lee el contenido del directorio asociado con el archivo y devuelve una porción de hasta n nombres de archivos en el directorio, en orden de directorio. Las llamadas posteriores en el mismo archivo generarán más nombres.

...

Si n <= 0, Readdirnames devuelve todos los nombres del directorio en un solo segmento.

Retazo:

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

Crédito para SquattingSlavInTracksuit 's comentario ; Hubiera sugerido promocionar su comentario a una respuesta si pudiera.

Jacob Kopczynski
fuente