- Tôi cần viết một hàm mà khi được cung cấp đường dẫn của một thư mục sẽ quét các tệp bắt nguồn từ thư mục đó.
- Và sau đó tôi cần hiển thị cấu trúc thư mục tại thư mục đó.
Tôi biết cách làm 2 (Tôi sẽ sử dụng jstree để hiển thị nó trong trình duyệt).
Tôi biết cách làm 2 (Tôi sẽ sử dụng jstree để hiển thị nó trong trình duyệt).
Câu trả lời:
CHỈNH SỬA : Có đủ người vẫn nhấn câu trả lời này, rằng tôi nghĩ rằng tôi sẽ cập nhật nó cho API Go1. Đây là một ví dụ hoạt động của filepath.Walk () . Bản gốc ở bên dưới.
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)
}
Xin lưu ý rằng filepath.Walk đi qua đệ quy cây thư mục.
Đây là một ví dụ chạy:
$ 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>
CÂU TRẢ LỜI GỐC SAU ĐÂY: Giao diện cho đường dẫn tệp đi bộ đã thay đổi kể từ hàng tuần. 2011-09-16, hãy xem http://groups.google.com/group/golang-nuts/msg/e304dd9cf196a218 . Đoạn mã dưới đây sẽ không hoạt động cho các phiên bản phát hành của GO trong tương lai gần.
Thực ra có một chức năng trong lib tiêu chuẩn chỉ dành cho điều này: 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)
}
filepath.Walk
nhân tiện không tuân theo các liên kết tượng trưng.
filepath.Walk
lại @FacescoPasa sẽ được kích hoạt trên các liên kết tượng trưng (cả tệp và thư mục). Có, nó sẽ không theo dõi chúng, nhưng lệnh gọi lại nhận ra một liên kết tượng trưng và thực hiện thêm hành động tức là một tiếp theo filepath.Walk
đảm bảo trước tiên rằng đường dẫn chưa được truy cập.
Đây là một cách để lấy thông tin tệp cho các tệp trong một thư mục.
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")
}
}
}
Readdir
tham số phương thức là n
một int
. Nếu n <= 0
, Readdir
trả về tất cả FileInfo
từ thư mục trong một lát.
os
func (FileMode) IsRegular
.
Đây là một ví dụ để lặp qua tất cả các tệp và thư mục một cách đệ quy. Lưu ý rằng nếu bạn muốn biết liệu đường dẫn bạn đang thêm vào có phải là một thư mục hay không, chỉ cần kiểm tra "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)
}
}
main
phương pháp không nên có ([]string, error)
args và bạn cần phải làm điều gì đó với err
. Trừ khi tại thời điểm trả lời nó đã hợp lệ? Chắc chắn là lỗi biên dịch trong các phiên bản gần đây hơn. Nếu không, rất hữu ích, cảm ơn bạn.
Gói github.com/kr/fs
cung cấp một Walker
API rất thú vị.
Gói tiêu chuẩn Go ioutil
đã được tích hợp sẵn chức năng cho trường hợp này, xem ví dụ bên dưới
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())
}
}
Lưu ý rằng "Walk không tuân theo các liên kết tượng trưng" vì vậy nếu bạn đang tìm cách viết một hàm làm được điều đó, tôi khuyên bạn nên sử dụng ioutil.ReadDir . Kiểm tra điểm chuẩn của riêng tôi cho thấy rằng nó nhanh hơn và ít tốn bộ nhớ hơn filepath.Glob .
Ngoài ra, ioutil.ReadDir
sắp xếp các tệp theo tên cơ sở bằng cách sử dụng so sánh chuỗi cơ bản ( strA > strB
). Với tư cách là một nhà phát triển, tôi thường sắp xếp các tên dir bằng cách so sánh số ngược (ví dụ: bản dựng mới nhất trước). Nếu đó cũng là trường hợp của bạn thì tốt hơn là bạn nên gọi trực tiếp os.ReadDir ( ioutil.ReadDir
đang gọi điều này dưới vỏ bọc) và tự mình phân loại.
Đây là một ví dụ về ReadDir
phần có sắp xếp theo kiểu số:
// 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
}
Bạn có thể muốn thực hiện chức năng cà ri ở đây, để bạn có thể sử dụng đầy đủ tìm kiếm
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)
return nil
}
}