Go编写的目录遍历器在遇到文件正在使用(被锁定)的错误时停止。

huangapple go评论125阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2017年3月31日 04:50:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/43128059.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定