user1540982
user1540982

Reputation: 71

Directory walker written in Go stops with file in use (locked) error

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?

Upvotes: 0

Views: 450

Answers (1)

apxp
apxp

Reputation: 5894

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.

Upvotes: 1

Related Questions