web-dev-qa-db-fra.com

Comment effectuer l'analyse du système de fichiers dans Golang?

  1. J'ai besoin d'écrire une fonction qui, une fois le chemin d'accès d'un dossier donné, analyse les fichiers enracinés dans ce dossier. 
  2. Et puis je dois afficher la structure de répertoire dans ce dossier. 

Je sais faire 2 (je vais utiliser jstree pour l’afficher dans le navigateur). 

Aidez-moi s'il vous plaît avec la partie 1, comme quoi/où commencer pour écrire une telle fonction Au go.

95
chinmay

EDIT: le nombre de personnes qui répondaient toujours à cette question était assez élevé pour que je puisse le mettre à jour pour l'API Go1. Ceci est un exemple de travail de filepath.Walk () . L'original est ci-dessous.

package main

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

func visit(path string, f os.FileInfo, err error) error {
  fmt.Printf("Visited: %s\n", path)
  return nil
} 


func main() {
  flag.Parse()
  root := flag.Arg(0)
  err := filepath.Walk(root, visit)
  fmt.Printf("filepath.Walk() returned %v\n", err)
}

Veuillez noter que filepath.Walk parcourt l'arborescence de répertoires de manière récursive.

Ceci est un exemple exécuté:

$ mkdir -p dir1/dir2
$ touch dir1/file1 dir1/dir2/file2
$ go run walk.go dir1
Visited: dir1
Visited: dir1/dir2
Visited: dir1/dir2/file2
Visited: dir1/file1
filepath.Walk() returned <nil>

RÉPONSES ORIGINALES SUIVANTES: L'interface pour parcourir les chemins d'accès aux fichiers a été modifiée à partir du 2011-11-16, voir http://groups.google.com/group/golang-nuts/msg/e304dd9cf196a218 . Le code ci-dessous ne fonctionnera pas pour les versions finales de GO dans un avenir proche.

Il y a en fait une fonction dans la bibliothèque standard juste pour ceci: filepath.Walk .

package main

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

type visitor int

// THIS CODE NO LONGER WORKS, PLEASE SEE ABOVE
func (v visitor) VisitDir(path string, f *os.FileInfo) bool {
    println(path)
    return true
} 

func (v visitor) VisitFile(path string, f *os.FileInfo) {
    println(path)
}

func main() {
    root := flag.Arg(0)
    filepath.Walk(root, visitor(0), nil)
}
185
laslowh

Voici un moyen d'obtenir des informations sur les fichiers d'un répertoire.

package main

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

func main() {
    dirname := "." + string(filepath.Separator)
    d, err := os.Open(dirname)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    defer d.Close()
    fi, err := d.Readdir(-1)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    for _, fi := range fi {
        if fi.Mode().IsRegular() {
            fmt.Println(fi.Name(), fi.Size(), "bytes")
        }
    }
}
15
peterSO

Voici un exemple pour parcourir tous les fichiers et répertoires de manière récursive. Notez que si vous voulez savoir si le chemin que vous ajoutez est un répertoire, cochez "f.IsDir ()".

package main

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

func main() {
    searchDir := "c:/path/to/dir"

    fileList := []string{}
    err := filepath.Walk(searchDir, func(path string, f os.FileInfo, err error) error {
        fileList = append(fileList, path)
        return nil
    })

    for _, file := range fileList {
        fmt.Println(file)
    }
}
12
Francois

Package github.com/kr/fs fournit une Walker avec une API très intéressante.

6
Mostafa

Aller au paquet standard ioutil a une fonction intégrée pour ce scénario, voir l'exemple ci-dessous 

func searchFiles(dir string) { // dir is the parent directory you what to search
    files, err := ioutil.ReadDir(dir)
    if err != nil {
        log.Fatal(err)
    }

    for _, file := range files {
        fmt.Println(file.Name())
    }
}
4
Jimmy Obonyo Abor

Notez que "Walk ne suit pas les liens symboliques", donc si vous cherchez à écrire une fonction qui le fasse, je vous recommande ioutil.ReadDir . Mon propre test de référence a montré qu'il est plus rapide et moins gourmand en mémoire que filepath.Glob .

De plus, ioutil.ReadDir trie les fichiers par nom de base en utilisant la comparaison de chaîne de base (strA > strB). En tant que développeur, je trie généralement les noms de répertoires en effectuant une comparaison numérique inverse (la dernière construction en premier, par exemple). Si c'est également votre cas, il est préférable d'appeler os.ReadDir directement (ioutil.ReadDir appelle cela sous la couverture) et de faire le tri vous-même.

Voici un exemple de la partie ReadDir avec le tri numérique:

// ReadDirNumSort - Same as ioutil/ReadDir but uses returns a Numerically
// Sorted file list.
//
// Taken from https://golang.org/src/io/ioutil/ioutil.go
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// Modified Sort method to use Numerically sorted names instead.
// It also allows reverse sorting.
func ReadDirNumSort(dirname string, reverse bool) ([]os.FileInfo, error) {
    f, err := os.Open(dirname)
    if err != nil {
        return nil, err
    }
    list, err := f.Readdir(-1)
    f.Close()
    if err != nil {
        return nil, err
    }
    if reverse {
        sort.Sort(sort.Reverse(byName(list)))
    } else {
        sort.Sort(byName(list))
    }
    return list, nil
}

// byName implements sort.Interface.
type byName []os.FileInfo

func (f byName) Len() int      { return len(f) }
func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
func (f byName) Less(i, j int) bool {
    nai, err := strconv.Atoi(f[i].Name())
    if err != nil {
        return f[i].Name() < f[j].Name()
    }
    naj, err := strconv.Atoi(f[j].Name())
    if err != nil {
        return f[i].Name() < f[j].Name()
    }
    return nai < naj
}
1
DavidG

https://github.com/030/go-find

package main

import (
    "log"

    find "github.com/030/go-find/find"
)

func main() {
    path, err := find.File("/home/user/go/src/github.com/030", "find.go")
    if err != nil {
        log.Fatal(err)
    }
}

résultats

/home/user/go/src/github.com/030/go-find/find/find.go
0
030