Diretório de lista no Go

197

Eu tenho tentado descobrir como simplesmente listar os arquivos e pastas em um único diretório no Go.

Eu encontrei filepath.Walk, mas ele entra em subdiretórios automaticamente, o que eu não quero. Todas as minhas outras pesquisas não melhoraram nada.

Tenho certeza de que essa funcionalidade existe, mas tem sido muito difícil de encontrar. Deixe-me saber se alguém sabe onde eu devo procurar. Obrigado.

Behram Mistree
fonte

Respostas:

359

Você pode tentar usar a função ReadDir no io/ioutilpacote. De acordo com os documentos:

ReadDir lê o diretório nomeado por dirname e retorna uma lista de entradas de diretório classificadas.

A fatia resultante contém os.FileInfotipos, que fornecem os métodos listados aqui . Aqui está um exemplo básico que lista o nome de tudo no diretório atual (as pastas estão incluídas, mas não são especialmente marcadas - você pode verificar se um item é uma pasta usando o 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())
    }
}
RocketDonkey
fonte
7
Se você só quer os nomes dos conteúdos de um diretório e velocidade é da essência, nota que o uso Readdirnames é ordens de magnitude mais rápido (cerca de 20x mais rápido para mim)
SquattingSlavInTracksuit
2
@SquattingSlavInTracksuit: promovi o seu comentário aqui para uma resposta, porque não tinha privilégios de comentário no momento. Se você preferir responder e receber o crédito, LMK.
Jacob Kopczynski
2
@SquattingSlavInTracksuit - essa é apenas uma ordem de grandeza: P
nadavvadan
78

Ainda mais simples, 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
fonte
8
Note 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
Certifique-se de entender o que o Glob faz antes de usá-lo. golang.org/pkg/path/filepath/#Glob
Anfernee
66

Podemos obter uma lista de arquivos dentro de uma pasta no sistema de arquivos usando várias funções da biblioteca padrão 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

O path/filepathpacote fornece uma maneira prática de verificar todos os arquivos em um diretório; ele verificará automaticamente cada subdiretório no diretório.

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 lê o diretório nomeado por dirname e retorna uma lista de entradas do diretório classificadas por nome de arquivo.

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

O Readdir lê o conteúdo do diretório associado ao arquivo e retorna uma fatia de até n valores FileInfo, como seria retornado por Lstat, na ordem do diretório. As chamadas subseqüentes no mesmo arquivo produzirão mais 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 referência.

pontuação de referência

Obtenha mais detalhes sobre esta postagem do blog

manigandand
fonte
3
A resposta mais completa aqui. Vale ressaltar que não há uso de memória ou alocações relatadas por este benchmark. É possível que as implementações mais rápidas usem mais memória. Também é possível que o número de núcleos da CPU no computador do testador prejudique / ajude o concorrente filepath.Walk. Além disso, filepath.Walksuporta recursivo decente enquanto os.File.Readdire ioutil.ReadDirnão.
Xeoncross
24

ioutil.ReadDiré uma boa descoberta, mas se você clicar e examinar a fonte, verá que ela chama o método Readdir do os.File . Se você concorda com a ordem do diretório e não precisa da lista classificada, esse método Readdir é tudo o que você precisa.

Sonia
fonte
7

Na sua descrição, o que você provavelmente quer é os.Readdirnames .

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

Readdirnames lê o conteúdo do diretório associado ao arquivo e retorna uma fatia de até n nomes de arquivos no diretório, em ordem de diretório. As chamadas subseqüentes no mesmo arquivo renderão outros nomes.

...

Se n <= 0, Readdirnames retorna todos os nomes do diretório em uma única fatia.

Snippet:

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 o comentário de SquattingSlavInTracksuit ; Eu teria sugerido promover o comentário deles para uma resposta, se pudesse.

Jacob Kopczynski
fonte