os.ReadDir în Go

Returnează conținutul unui director (fișiere și subdirectoare), sortat după nume.

Sintaxă
func ReadDir(name string) ([]DirEntry, error)

Ce face os.ReadDir

os.ReadDir citește tot directorul și returnează intrările ca []os.DirEntry, sortate alfabetic după nume. Fiecare intrare are Name(), IsDir(), Type() (tipul: fișier, director, legătură) și Info(), care returnează FileInfo-ul complet (dimensiune, dată) doar când ai nevoie de el.

Funcția nu intră în subdirectoare; pentru parcurgere recursivă folosește filepath.WalkDir. Pentru a găsi fișiere după un model (*.jpg) folosește filepath.Glob. Dacă apare o eroare la jumătatea citirii, primești intrările citite până atunci și eroarea.

Parametri

Parametru Descriere
name Calea directorului.

Ce returnează

Intrările directorului, sortate, și nil, sau intrările citite și o eroare.

Exemple

Exemplul 1: Listarea unui director

Sortarea este după octeți, nu după alfabetul obișnuit: numele cu majusculă (README.md) vin înaintea celor cu literă mică.

package main

import (
    "fmt"
    "os"
)

func main() {
    os.MkdirAll("proiect/docs", 0o755)
    os.MkdirAll("proiect/cmd", 0o755)
    os.WriteFile("proiect/main.go", nil, 0o644)
    os.WriteFile("proiect/go.mod", nil, 0o644)
    os.WriteFile("proiect/README.md", nil, 0o644)

    intrari, err := os.ReadDir("proiect")
    if err != nil {
        fmt.Println("eroare:", err)
        return
    }
    for _, e := range intrari {
        if e.IsDir() {
            fmt.Println("[dir] ", e.Name())
        } else {
            fmt.Println("      ", e.Name())
        }
    }
}

Rezultat

       README.md
[dir]  cmd
[dir]  docs
       go.mod
       main.go

Exemplul 2: Mărimea totală a imaginilor

Info() aduce dimensiunea doar pentru intrările care ne interesează.

package main

import (
    "fmt"
    "os"
    "path/filepath"
    "strings"
)

func main() {
    os.Mkdir("poze", 0o755)
    os.WriteFile("poze/mare.jpg", make([]byte, 4000), 0o644)
    os.WriteFile("poze/munte.JPG", make([]byte, 2500), 0o644)
    os.WriteFile("poze/lista.txt", make([]byte, 100), 0o644)

    intrari, _ := os.ReadDir("poze")
    var total int64
    for _, e := range intrari {
        if e.IsDir() || strings.ToLower(filepath.Ext(e.Name())) != ".jpg" {
            continue
        }
        info, err := e.Info()
        if err != nil {
            continue
        }
        total += info.Size()
        fmt.Printf("%-10s %5d octeți\n", e.Name(), info.Size())
    }
    fmt.Println("total:", total, "octeți")
}

Rezultat

mare.jpg    4000 octeți
munte.JPG   2500 octeți
total: 6500 octeți

Exemplul 3: Director inexistent

package main

import (
    "fmt"
    "os"
)

func main() {
    intrari, err := os.ReadDir("arhiva-2019")
    fmt.Println(len(intrari), err)

    os.WriteFile("nota.txt", nil, 0o644)
    _, err = os.ReadDir("nota.txt")
    fmt.Println(err)
}

Rezultat

0 open arhiva-2019: no such file or directory
open nota.txt: not a directory

Greșeli frecvente

  • Folosești os.ReadDir pe directoare uriașe (sute de mii de fișiere): toate intrările ajung în memorie și sunt sortate. Deschide directorul cu os.Open și citește în loturi cu f.ReadDir(n).
  • Apelezi e.Info() pentru fiecare intrare doar ca să afli dacă e director. e.IsDir() nu mai citește nimic de pe disc.

Comenzi înrudite

  • os.File.ReadDir: Citește intrările (fișiere și subdirectoare) dintr-un director deschis.
  • filepath.WalkDir: Parcurge recursiv un director și apelează o funcție pentru fiecare fișier și subdirector, în ordine alfabetică.
  • filepath.Glob: Returnează toate fișierele de pe disc ale căror nume se potrivesc unui model cu *, ? și [ ].
  • os.Stat: Returnează informațiile unui fișier (dimensiune, drepturi, dată, director sau nu) fără să-l deschidă; Lstat nu urmează legăturile.
  • os.Mkdir: Creează un singur director nou; dă eroare dacă există deja sau dacă directorul părinte lipsește.