czy potrzebujesz go do rekurencyjnego przechodzenia przez drzewo katalogów?
newacct
Odpowiedzi:
194
EDYCJA : Wystarczająco dużo osób wciąż trafia na tę odpowiedź, że pomyślałem, że zaktualizuję ją dla API Go1. To jest działający przykład filepath.Walk () . Oryginał znajduje się poniżej.
package main
import("path/filepath""os""flag""fmt")
func visit(path string, f os.FileInfo, err error) error {
fmt.Printf("Visited: %s\n", path)returnnil}
func main(){
flag.Parse()
root := flag.Arg(0)
err := filepath.Walk(root, visit)
fmt.Printf("filepath.Walk() returned %v\n", err)}
Należy pamiętać, że filepath.Walk przechodzi przez drzewo katalogów rekurencyjnie.
Oto przykładowy bieg:
$ 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>
ORYGINALNA ODPOWIEDŹ NASTĘPUJĄCA: Interfejs ścieżek do plików spacerowych zmienił się co tydzień w 2011-09-16, patrz http://groups.google.com/group/golang-nuts/msg/e304dd9cf196a218 . Poniższy kod nie będzie działał z wydanymi wersjami GO w najbliższej przyszłości.
Właściwie w standardowej bibliotece znajduje się funkcja przeznaczona tylko do tego: 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)returntrue}
func (v visitor)VisitFile(path string, f *os.FileInfo){
println(path)}
func main(){
root := flag.Arg(0)
filepath.Walk(root, visitor(0),nil)}
filepath.Walkprzy okazji nie podąża za linkami symbolicznymi.
0xcaff
3
Wywołanie filepath.Walkzwrotne @FrancescoPasa zostanie uruchomione na dowiązaniach symbolicznych (zarówno plik, jak i katalog). Tak, nie podąży za nimi, ale wywołanie zwrotne rozpozna łącze symboliczne i podejmie dalsze działania, tj. Kontynuację, filepath.Walkupewniając się najpierw, że ścieżka nie została już odwiedzona.
colm.anseo
15
Oto sposób na uzyskanie informacji o plikach w katalogu.
@peterSO: co oznacza Readdir (-1)? ponieważ Readdir akceptuje tylko typ ciągu znaków i na podstawie dokumentacji API, ciąg nie może mieć tylko wartości NUL i żadnych innych ograniczeń .. i jaki jest typ zwracanego elementu „fi” w Readdir, w jaki sposób można go przejść (czy to mapa?) ..
sateayam
@heike: Zobacz moją poprawioną odpowiedź, która zawiera teraz dokumentację API. Jak widać, Readdirparametrem metody jest nplik int. Jeśli n <= 0, Readdirzwraca wszystkie FileInfoz katalogu w jednym wycinku.
nie być wybrednym, ale odroczenie zamknięcia powinno nastąpić przed sprawdzeniem błędów.
Zanven
13
Oto przykład rekurencyjnej pętli przez wszystkie pliki i katalogi. Zauważ, że jeśli chcesz wiedzieć, czy dołączana ścieżka jest katalogiem, po prostu zaznacz "f.IsDir ()".
Czy skopiowałeś i wkleiłeś funkcję? mainMetoda nie powinna mieć ([]string, error)args i trzeba coś zrobić z err. Chyba że w chwili udzielenia odpowiedzi był ważny? Zdecydowanie błąd kompilacji w nowszych wersjach. W przeciwnym razie bardzo przydatne, dziękuję.
Standardowy pakiet Go ioutilma wbudowaną funkcję dla tego przypadku, patrz poniższy przykład
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())}}
Pamiętaj, że „Spacer nie podąża za dowiązaniami symbolicznymi”, więc jeśli chcesz napisać funkcję, która to robi, polecam ioutil.ReadDir . Mój własny test porównawczy wykazał, że jest szybszy i mniej obciążający pamięć niż filepath.Glob .
Dodatkowo ioutil.ReadDirsortuje pliki według basename przy użyciu podstawowego porównania ciągów ( strA > strB). Jako deweloper generalnie sortuję nazwy katalogów, wykonując odwrotne porównanie liczbowe (na przykład najnowsza kompilacja jako pierwsza). Jeśli tak jest również w twoim przypadku, lepiej zadzwonić bezpośrednio do os.ReadDir ( ioutil.ReadDirwywołuje to pod okładkami) i przeprowadzić sortowanie samodzielnie.
Oto przykład ReadDirczęści z sortowaniem numerycznym:
// 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{returnnil, err
}
list, err := f.Readdir(-1)
f.Close()if err !=nil{returnnil, 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
}
Możesz tutaj skorzystać z funkcji curry, abyś mógł w pełni wykorzystać wyszukiwanie
func visit(files *[]string) filepath.WalkFunc{return func (path string, info os.FileInfo, err error) error {// maybe do this in some if block*files = append(*files, path)returnnil}}
Odpowiedzi:
EDYCJA : Wystarczająco dużo osób wciąż trafia na tę odpowiedź, że pomyślałem, że zaktualizuję ją dla API Go1. To jest działający przykład filepath.Walk () . Oryginał znajduje się poniżej.
Należy pamiętać, że filepath.Walk przechodzi przez drzewo katalogów rekurencyjnie.
Oto przykładowy bieg:
ORYGINALNA ODPOWIEDŹ NASTĘPUJĄCA: Interfejs ścieżek do plików spacerowych zmienił się co tydzień w 2011-09-16, patrz http://groups.google.com/group/golang-nuts/msg/e304dd9cf196a218 . Poniższy kod nie będzie działał z wydanymi wersjami GO w najbliższej przyszłości.
Właściwie w standardowej bibliotece znajduje się funkcja przeznaczona tylko do tego: filepath.Walk .
źródło
filepath.Walk
przy okazji nie podąża za linkami symbolicznymi.filepath.Walk
zwrotne @FrancescoPasa zostanie uruchomione na dowiązaniach symbolicznych (zarówno plik, jak i katalog). Tak, nie podąży za nimi, ale wywołanie zwrotne rozpozna łącze symboliczne i podejmie dalsze działania, tj. Kontynuację,filepath.Walk
upewniając się najpierw, że ścieżka nie została już odwiedzona.Oto sposób na uzyskanie informacji o plikach w katalogu.
źródło
Readdir
parametrem metody jestn
plikint
. Jeślin <= 0
,Readdir
zwraca wszystkieFileInfo
z katalogu w jednym wycinku.os
func (FileMode) IsRegular
.Oto przykład rekurencyjnej pętli przez wszystkie pliki i katalogi. Zauważ, że jeśli chcesz wiedzieć, czy dołączana ścieżka jest katalogiem, po prostu zaznacz "f.IsDir ()".
źródło
main
Metoda nie powinna mieć([]string, error)
args i trzeba coś zrobić zerr
. Chyba że w chwili udzielenia odpowiedzi był ważny? Zdecydowanie błąd kompilacji w nowszych wersjach. W przeciwnym razie bardzo przydatne, dziękuję.Pakiet
github.com/kr/fs
zawieraWalker
bardzo ciekawe API.źródło
Standardowy pakiet Go
ioutil
ma wbudowaną funkcję dla tego przypadku, patrz poniższy przykładźródło
Pamiętaj, że „Spacer nie podąża za dowiązaniami symbolicznymi”, więc jeśli chcesz napisać funkcję, która to robi, polecam ioutil.ReadDir . Mój własny test porównawczy wykazał, że jest szybszy i mniej obciążający pamięć niż filepath.Glob .
Dodatkowo
ioutil.ReadDir
sortuje pliki według basename przy użyciu podstawowego porównania ciągów (strA > strB
). Jako deweloper generalnie sortuję nazwy katalogów, wykonując odwrotne porównanie liczbowe (na przykład najnowsza kompilacja jako pierwsza). Jeśli tak jest również w twoim przypadku, lepiej zadzwonić bezpośrednio do os.ReadDir (ioutil.ReadDir
wywołuje to pod okładkami) i przeprowadzić sortowanie samodzielnie.Oto przykład
ReadDir
części z sortowaniem numerycznym:źródło
Możesz tutaj skorzystać z funkcji curry, abyś mógł w pełni wykorzystać wyszukiwanie
źródło