Сканирование файловых систем в Golang
- Мне нужно написать функцию, которая при заданном пути к папке
сканирует файлы, размещенные в этой папке. - и затем мне нужно, чтобы отобразить структуру каталогов в этой папке.
Я знаю, как сделать 2 (я собираюсь использовать jstree для отображения его в браузере).
пожалуйста, помогите мне с частью 1, например, что / где начать писать такое
функция в go.
6 ответов:
EDIT: достаточно людей все еще ударил этот ответ, что я думал, что я бы обновить его для GO1 API. Это рабочий пример путь_к_файлу.Прогулка (). Оригинал находится ниже.
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) }обратите внимание, что путь.Прогулка идет по дереву каталогов рекурсивно.
Это пример запуска:
$ 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>ОРИГИНАЛЬНЫЙ ОТВЕТ СЛЕДУЕТ: интерфейс для ходьбы пути к файлам изменился с еженедельной.2011-09-16 см. http://groups.google.com/group/golang-nuts/msg/e304dd9cf196a218. приведенный ниже код не будет работать для версий релиза GO в ближайшем будущем.
есть на самом деле функция в стандартной lib только для этого: путь_к_файлу.Гуляй.
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) }
вот способ получения информации о файлах для файлов в каталоге.
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") } } }
вот пример рекурсивного перебора всех файлов и каталогов. Обратите внимание, что если вы хотите знать, является ли путь, который вы добавляете, каталогом, просто проверьте "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) } }
пакета
github.com/kr/fsпредоставляетWalkerС очень интересным API.
перейти стандартный пакет
ioutilимеет встроенную функцию для этого случая сценария см. ниже пример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()) } }
обратите внимание ,что "прогулка не следует символическим ссылкам", поэтому, если вы хотите написать функцию, которая делает это, я рекомендую ioutil.ReadDir. Мой собственный тест бенчмарка показал, что это быстрее и менее интенсивно памяти, чем путь_к_файлу.Глоб.
кроме того,
ioutil.ReadDirсортирует файлы по базовому имени, используя базовое сравнение строк (strA > strB). Как парень devops, я обычно сортирую имена dir, выполняя обратное численное сравнение (например, последняя сборка). Если это тоже ваш случай, то лучше назвать ОС.ReadDir напрямую (ioutil.ReadDirвызывает это под обложками) и сделайте сортировку самостоятельно.вот пример
ReadDirчасть с числовой вид:// 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 }
Comments