Search code examples
linuxgopermissionschmod

Golang chmod files and directories recursively


I'm trying to use WalkDir with Chmod to recursively change the permission of a directory and its files and subdirectories. Somehow it does just change the first file or directory of the given path and stops afterwards. Can someone spot the mistake? getFileMode just converts the string "755" in os.FileMode(0755) and returns it.

func ChmodRec(path string, di fs.DirEntry, err error) error {
    fileMode, err2 := getFileMode(os.Getenv("CHMOD_MODE"))
    if err2 != nil {
        log.Fatal("Could not set file mode for chmodding", path)
        panic(err)
    }

    err2 = os.Chmod(path, fileMode)
    if err2 != nil {
        fmt.Println("Could not chmod", path)
        panic(err)
    }
    fmt.Println("Changing mode of", path)
    return nil
}

func ChmodRecursive(path string, mode string) {
    os.Setenv("CHMOD_MODE", mode)
    err := filepath.WalkDir(path, ChmodRec)
    if err != nil {
        log.Fatal("Could not chmod recursively ", path)
        panic(err)
    }
}

func main() {
    path := "bla/test/"
    mode := "755"
    ChmodRecursive(path, mode)
}

Solution

  • Your code does not check err argument in ChmodRec. This is an extract from official documentation:

    WalkDir calls the function with a non-nil err argument in two cases.

    First, if the initial fs.Stat on the root directory fails, WalkDir calls the function with path set to root, d set to nil, and err set to the error from fs.Stat.

    Second, if a directory's ReadDir method fails, WalkDir calls the function with path set to the directory's path, d set to an fs.DirEntry describing the directory, and err set to the error from ReadDir. In this second case, the function is called twice with the path of the directory: the first call is before the directory read is attempted and has err set to nil, giving the function a chance to return SkipDir and avoid the ReadDir entirely. The second call is after a failed ReadDir and reports the error from ReadDir. (If ReadDir succeeds, there is no second call.)

    Add this code to the beginning of the function. It can give you a hint:

    func ChmodRec(path string, di fs.DirEntry, err error) error {
            if err != nil {
                log.Fatal(err)
            }