107 votes

Comment effectuer une analyse du système de fichiers

  1. J'ai besoin d'écrire une fonction qui, lorsqu'on lui donne le chemin d'un dossier parcourt les fichiers qui se trouvent dans ce dossier.
  2. Et ensuite, j'ai besoin d'afficher la structure du répertoire dans ce dossier.

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

2 votes

Avez-vous besoin qu'il parcoure l'arborescence des répertoires de manière récursive ?

211voto

laslowh Points 3209

EDIT POUR 1.16 : Il y a encore suffisamment de personnes qui consultent cette réponse, pour que je pense la mettre à jour pour Go 1.16.

La fonction filepath.WalkDir introduit dans Go 1.16 a de meilleures performances que filepath.Walk mentionné dans l'édition précédente. Voici un exemple fonctionnel :

package main

import (
    "flag"
    "fmt"
    "io/fs"
    "path/filepath"
)

func visit(path string, di fs.DirEntry, err error) error {
    fmt.Printf("Visited: %s\n", path)
    return nil
}

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

EDIT : Il y a encore suffisamment de personnes qui consultent cette réponse pour que je la mette à jour pour l'API Go1. Il s'agit d'un exemple fonctionnel 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 l'arbre des répertoires de manière récursive.

Il s'agit d'un exemple d'exécution :

$ 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>

LA RÉPONSE ORIGINALE SUIT : L'interface permettant de parcourir les chemins de fichiers a été modifiée à partir de la semaine 2011-09-16, cf. http://groups.google.com/group/golang-nuts/msg/e304dd9cf196a218 . Le code ci-dessous ne fonctionnera pas pour les versions de GO dans un avenir proche.

Il y a en fait une fonction dans la librairie standard juste pour ça : 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)
}

1 votes

filepath.Walk ne suit pas les liens symboliques d'ailleurs.

3 votes

@FrancescoPasa filepath.Walk sera déclenché sur les liens symboliques (fichiers et répertoires). Oui, il ne sera pas suivez mais le callback reconnaît un lien symbolique et prend des mesures supplémentaires, c'est-à-dire un suivi. filepath.Walk en s'assurant d'abord que le chemin n'a pas déjà été visité.

16voto

peterSO Points 25725

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

0 votes

@peterSO : que signifie Readdir(-1) ? car Readdir n'accepte que les chaînes de caractères, et d'après la documentation de l'API, une chaîne de caractères peut seulement ne pas être NUL, et aucune autre limitation et quel est le type de retour de "fi" dans Readdir, comment se fait-il qu'on puisse le parcourir (est-ce une carte ?) .

0 votes

@heike : Voir ma réponse révisée, qui inclut désormais la documentation de l'API. Comme vous pouvez le constater, la Readdir Le paramètre de la méthode est n un int . Si n <= 0 , Readdir renvoie tous les FileInfo du répertoire en une seule tranche.

0 votes

@RickSmith : Voir le paquet os func (FileMode) IsRegular .

13voto

Francois Points 181

Voici un exemple pour parcourir en boucle 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, vérifiez simplement "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)
    }
}

0 votes

Avez-vous copié et collé une fonction ? Le site main ne devrait pas avoir ([]string, error) et vous devez faire quelque chose avec err . A moins qu'au moment de la réponse, elle n'ait été valide ? Certainement une erreur de compilation dans les versions plus récentes. Sinon, très utile, merci.

7voto

Mostafa Points 7468

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

-2voto

BlackNoxis Points 31

Comme je l'ai expliqué dans d'autres fils, il y a une petite faille dans l'utilisation de os.Open(whatever). Disons que si vous mettez un

fmt.Printf("Name a directory which you want to scan for files: \n")
var i string
fmt.Scanf("%s",&i)
d, err := os.Open(i)

Et si vous entrez deux mots ou plus, il essaiera d'ouvrir les commandes représentant ces mots (comme os.Open déclare les commandes /usr/bin/ ou tout autre chemin et les utilise pour de vrai). Par conséquent, la méthode consistant à utiliser os.Open pour essayer d'abord d'ouvrir le fichier et ensuite trouver ses propriétés n'est pas tout à fait méthodique. Vous devriez effectivement utiliser des fonctions qui analysent ses propriétés et filtrent ce dont vous avez besoin (si c'est un fichier, un répertoire, ou des sortes).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X