Каталог списків у Go


198

Я намагався розібратися, як просто перерахувати файли та папки в одному каталозі в Go.

Я знайшов filepath.Walk, але він автоматично надходить у підкаталоги, чого я не хочу. Усі мої пошуки не покращили нічого.

Я впевнений, що ця функціональність існує, але її знайти насправді важко. Повідомте мене, якщо хтось знає, куди я повинен шукати. Дякую.

Відповіді:


360

Ви можете спробувати використовувати функцію ReadDir в io/ioutilпакеті. Документи:

ReadDir зчитує каталог, названий dirname, і повертає список відсортованих записів каталогів.

Отриманий фрагмент містить os.FileInfoтипи, які надають перелічені тут методи . Ось основний приклад, у якому перераховано назву всього, що знаходиться у поточній папці (папки включені, але спеціально не позначені - ви можете перевірити, чи є елемент папкою, використовуючи IsDir()метод):

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

8
Якщо ви хочете тільки імена вмісту каталогу та швидкість має суті, зверніть увагу , що використання Readdirnames є порядків швидше (близько 20x швидше для мене)
SquattingSlavInTracksuit

2
@SquattingSlavInTracksuit: Я просунув ваш коментар тут до відповіді, тому що я не мав привілеїв для коментарів на той час. Якщо ви бажаєте відповісти на це та отримати кредит, LMK.
Яків Копчинський

2
@SquattingSlavInTracksuit - це лише один порядок: P
nadavvadan

79

Ще простіше, використовуйте 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
Зауважимо, щоGlob ignores file system errors such as I/O errors reading directories. The only possible returned error is ErrBadPattern, when pattern is malformed.
Jon

3
Не забудьте зрозуміти, що робить Glob перед його використанням. golang.org/pkg/path/filepath/#Glob
Анферні

69

Ми можемо отримати список файлів всередині папки у файловій системі за допомогою різних стандартних функцій бібліотеки 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. Використання filepath.Walk

path/filepathПакет забезпечує зручний спосіб для сканування всіх файлів в каталозі, він буде автоматично сканувати кожен підкаталоги в каталозі.

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. Використання ioutil.ReadDir

ioutil.ReadDir читає каталог, названий dirname, і повертає список записів каталогів, відсортованих за іменем файлу.

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. Використання os.File.Readdir

Readdir зчитує вміст каталогу, пов'язаного з файлом, і повертає фрагмент до n значень FileInfo, як би повернув Lstat, у порядку каталогу. Подальші дзвінки в той самий файл нададуть додаткові дані 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
}

Результати порівняння.

бальна оцінка

Дізнайтеся більше про цю публікацію в блозі


3
Тут найповніша відповідь. Варто зазначити, що за цим еталоном не повідомляється про використання пам’яті або алоків. Можливо, що швидші реалізації використовують більше пам'яті. Можливо також, що кількість ядер CPU на комп'ютері тестера шкодить / допомагає одночасно filepath.Walk. Крім того, filepath.Walkпідтримує рекурсивні пристойний час os.File.Readdirі ioutil.ReadDirне роблять.
Xeoncross

24

ioutil.ReadDirце хороша знахідка, але якщо натиснути і подивитися на джерело, ви побачите, що він викликає метод Readdir з os.File . Якщо ви добре з порядком у каталозі та не потребуєте сортування списку, то цей метод Readdir - це все, що вам потрібно.


7

З вашого опису, що ви, мабуть, хочете, це os.Readdirnames .

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

Readdirnames читає вміст каталогу, пов'язаного з файлом, і повертає фрагмент до n імен файлів у каталозі, в порядку каталогу. Подальші дзвінки в одному файлі дадуть нові імена.

...

Якщо n <= 0, Readdirnames повертає всі імена з каталогу в один фрагмент.

Фрагмент:

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

Кредит SquattingSlavInTracksuit 's коментар ; Я б запропонував просувати їх коментар до відповіді, якби міг.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.