I would like to recursively create a directory and assign an owner and group for the folders and its parents that were created.
For example, assuming /var
exists, I want to create /var/test1/test2/test3
.
I am able to do this using os.MkdirAll("/var/test1/test2/test3", 0600)
.
However, I also want to set test1
, test2
, and test3
's uid
to user1
and gid
to user1
.
It's possible to do so using os.Chown
, but that requires a lot of manually work. I would need build a tree of the folder and its parents that do not exist before creating the folder chain and then use os.Chown
on each folder after creation.
Is there a simpler way?
A bit like this ChownR()
type of function, the idea would be to filter the walk, and apply the chown only to folders which are part of a path passed in parameter (here "/var/test1/test2/test3
)
Without filter:
func ChownR(path string, uid, gid int) error {
return filepath.Walk(path, func(name string, info os.FileInfo, err error) error {
if err == nil {
err = os.Chown(name, uid, gid)
}
return err
})
}
In other words, with filepath.Walk()
, there should not be too much "manual work" involved here.
Switch the mkdir process to the user you wish to create directories for. This has the advantage of creating directories with correct permissions and ownership in a single command instead of creating loops or running multiple commands back to back.
Example:
import "os/exec"
import "syscall"
func main() {
// The command here can use flags to create all of the dirs at once
cmd := exec.Command('mkdir', '-p', '/var/test1/test2/test3/')
_ = syscall.Umask(0077) // Set umask for this process
cmd.SysProcAttr = &syscall.SysProcAttr{}
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}
cmd.Run()
}
Since the subprocess "mkdir" runs as the user specified by uid
, the folders would already have the correct owner. If you get the umask part right, each directory will also have correct permissions.
One caveat: this is not a very portable solution. Using syscall should only be your solution if you are certain your code will only be executing on a specific OS.