英文:
Directory walker written in Go stops with file in use (locked) error
问题
我有一个目录遍历器:
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
)
var exts = [...]string{"*.psd", "*.cdr", "*.tiff", "*.svg", "*.png", "*.jpeg", "*.jpg", "*.pdf", "*.txt", "*.rtf", "*.docx", "*.doc", "*.xlsx", "*.xls", "*.ppt", "*.pptx", "*.accdb", "*.csv", "*.dwg", "*.dxf", "*.dng", "*.arw", "*.srf", "*.sr2", "*.bay", "*.crw", "*.cr2", "*.dcr", "*.kdc", "*.erf", "*.mef", "*.mrw", "*.nef", "*.nrw", "*.orf", "*.raf", "*.raw", "*.rwl", "*.rw2", "*.r3d", "*.ptx", "*.pef", "*.srw"}
var skipdir = [...]string{"WINDOWS", "Program Files"}
func VisitFile(fp string, fi os.FileInfo, err error) error {
proceed := true
if err != nil {
fmt.Println(err) // 无法遍历此处,
return nil // 但继续遍历其他地方
}
if fi.IsDir() {
return nil // 不是文件,忽略
}
for _, value := range skipdir {
if strings.Contains(filepath.Dir(fp), value) {
proceed = false
break
}
}
if proceed == true {
for _, value := range exts {
matched, err := filepath.Match(value, fi.Name())
if err != nil {
fmt.Println(err) // 模式错误
return err // 这是致命错误
}
if matched {
fmt.Println(fp)
}
}
} else {
//fmt.Println(proceed)
return nil
}
return nil
}
func getdrives() (r []string) {
for _, drive := range "ABCDEFGHIJKLMNOPQRSTUVWXYZ" {
_, err := os.Open(string(drive) + ":\\")
if err == nil {
r = append(r, string(drive))
}
}
return
}
func main() {
drives := getdrives()
for _, value := range drives {
filepath.Walk(value+":/", VisitFile)
}
}
然而,当它遇到 pagefile.sys 时,我收到以下消息:
GetFileAttributesEx C:\pagefile.sys: 由于文件正在被另一个进程使用,无法访问。
因为文件正在使用中,程序停止了。如何抑制此消息以继续遍历?
英文:
I have this directory walker:
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
)
var exts = [...]string{"*.psd", "*.cdr", "*.tiff", "*.svg", "*.png", "*.jpeg", "*.jpg", "*.pdf", "*.txt", "*.rtf", "*.docx", "*.doc", "*.xlsx", "*.xls", "*.ppt", "*.pptx", "*.accdb", "*.csv", "*.dwg", "*.dxf", "*.dng", "*.arw", "*.srf", "*.sr2", "*.bay", "*.crw", "*.cr2", "*.dcr", "*.kdc", "*.erf", "*.mef", "*.mrw", "*.nef", "*.nrw", "*.orf", "*.raf", "*.raw", "*.rwl", "*.rw2", "*.r3d", "*.ptx", "*.pef", "*.srw"}
var skipdir = [...]string{"WINDOWS", "Program Files"}
func VisitFile(fp string, fi os.FileInfo, err error) error {
proceed := true
if err != nil {
fmt.Println(err) // can't walk here,
return nil // but continue walking elsewhere
}
if fi.IsDir() {
return nil // not a file. ignore.
}
for _, value := range skipdir {
if strings.Contains(filepath.Dir(fp), value) {
proceed = false
break
}
}
if proceed == true {
for _, value := range exts {
matched, err := filepath.Match(value, fi.Name())
if err != nil {
fmt.Println(err) // malformed pattern
return err // this is fatal.
}
if matched {
fmt.Println(fp)
}
}
} else {
//fmt.Println(proceed)
return nil
}
return nil
}
func getdrives() (r []string) {
for _, drive := range "ABCDEFGHIJKLMNOPQRSTUVWXYZ" {
_, err := os.Open(string(drive) + ":\\")
if err == nil {
r = append(r, string(drive))
}
}
return
}
func main() {
drives := getdrives()
for _, value := range drives {
filepath.Walk(value+":/", VisitFile)
}
}
However, when it gets to pagefile.sys, I get this message:
> GetFileAttributesEx C:\pagefile.sys: The process cannot access the file because
it is being used by another process.
because the file is in use, and program stops. How do I suppress this message to continue walking?
答案1
得分: 1
如果你希望你的遍历完成,你不应该在函数内部返回错误。你应该将错误收集到一个切片中。
将你的函数改为:
// 在函数外部声明这个变量
var myErrors []error
func VisitFile(fp string, fi os.FileInfo, err error) []error {
// 做一个错误切片的变量。然后改变 return err
的部分
if proceed == true {
for _, value := range exts {
matched, err := filepath.Match(value, fi.Name())
if err != nil {
fmt.Println(err) // malformed pattern
// 收集错误
myErrors = append(myErrors,err)
// 你可以通过以下方式跳出循环
return nil
}
if matched {
fmt.Println(fp)
}
}
}
在最后你可以检查 myErrors
切片。
英文:
If you want your walk to finish, you should not return the error inside your function. You should collect the errors inside a slice.
Change your function to:
// Put this var outside your function
var myErrors []error
func VisitFile(fp string, fi os.FileInfo, err error) []error {
Just make a variable as slice of errors. And then change the return err
if proceed == true {
for _, value := range exts {
matched, err := filepath.Match(value, fi.Name())
if err != nil {
fmt.Println(err) // malformed pattern
// collect the error
myErrors = append(myErrors,err)
// you could jump out of this by
return nil
}
if matched {
fmt.Println(fp)
}
}
}
At the end you can check the myErrors
slice.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论