filepath.Walk în Go

Parcurge recursiv un director și apelează o funcție cu informațiile complete (FileInfo) ale fiecărei intrări.

Sintaxă
func Walk(root string, fn WalkFunc) error

// fn: func(path string, info fs.FileInfo, err error) error

Ce face filepath.Walk

filepath.Walk funcționează ca WalkDir: vizitează în ordine lexicală root și tot ce e sub el. Diferența este că funcția primește un fs.FileInfo complet (mărime, drepturi, dată), obținut cu os.Lstat pentru fiecare intrare. De aceea este mai lentă pe directoare mari.

Documentația recomandă WalkDir pentru cod nou. Walk rămâne util în cod existent sau când chiar ai nevoie de FileInfo pentru fiecare fișier. Valorile SkipDir și SkipAll funcționează la fel.

Parametri

Parametru Descriere
root Directorul de pornire.
fn Funcția apelată pentru fiecare intrare, cu calea, FileInfo și eventuala eroare.

Ce returnează

nil sau eroarea returnată de fn.

Exemple

Exemplul 1: Fișierele mai mari de 1 KB

package main

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

func main() {
    os.MkdirAll("arhiva/poze", 0o755)
    os.WriteFile("arhiva/nota.txt", make([]byte, 200), 0o644)
    os.WriteFile("arhiva/poze/mare.jpg", make([]byte, 5000), 0o644)
    os.WriteFile("arhiva/poze/mic.jpg", make([]byte, 800), 0o644)

    filepath.Walk("arhiva", func(cale string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if !info.IsDir() && info.Size() > 1024 {
            fmt.Printf("%s (%d octeți)\n", cale, info.Size())
        }
        return nil
    })
}

Rezultat

arhiva/poze/mare.jpg (5000 octeți)

Exemplul 2: Numărarea fișierelor și directoarelor

package main

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

func main() {
    os.MkdirAll("magazin/produse/carti", 0o755)
    os.WriteFile("magazin/index.html", nil, 0o644)
    os.WriteFile("magazin/produse/carti/1.json", nil, 0o644)
    os.WriteFile("magazin/produse/carti/2.json", nil, 0o644)

    fisiere, directoare := 0, 0
    filepath.Walk("magazin", func(_ string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if info.IsDir() {
            directoare++
        } else {
            fisiere++
        }
        return nil
    })
    fmt.Println("fișiere:", fisiere, "| directoare:", directoare)
}

Rezultat

fișiere: 3 | directoare: 3

Greșeli frecvente

  • Folosești info fără să verifici err. La erori, info poate fi nil.
  • Folosești Walk pe directoare cu sute de mii de fișiere și programul este lent. WalkDir evită apelul Lstat pentru fiecare fișier.

Comenzi înrudite

  • filepath.WalkDir: Parcurge recursiv un director și apelează o funcție pentru fiecare fișier și subdirector, în ordine alfabetică.
  • os.File.Stat: Returnează informații despre fișierul deschis: nume, dimensiune, drepturi, data modificării, dacă e director.
  • filepath.Glob: Returnează toate fișierele de pe disc ale căror nume se potrivesc unui model cu *, ? și [ ].