2015-10-16 68 views
2

我想递归地创建一个目录并为创建的文件夹及其父项分配一个所有者和组。递归地创建一个具有特定所有者和组的目录

例如,假设/var存在,我想创建/var/test1/test2/test3

我能够使用os.MkdirAll("/var/test1/test2/test3", 0600)来做到这一点。

不过,我也想设置test1test2test3uiduser1giduser1

使用os.Chown可以这样做,但这需要大量的手动工作。我需要在创建文件夹链之前构建不存在的文件夹及其父项的树,然后在创建后在每个文件夹上使用os.Chown

有没有更简单的方法?

+1

我不认为有这样的事情可用。你可能最好复制'MkdirAll'源文件并添加一个合适的'Chown'调用来做你想做的事(IIRC没有办法自动创建一个非默认所有者的目录)。 –

+1

我认为这是目前最好的选择,尽管它感觉像是一种代码味道。 – F21

回答

2

这样ChownR() type of function了一下,这个想法会过滤步行路程,CHOWN只适用于它们

参数(这里"/var/test1/test2/test3)所经过的路径的一部分,无需过滤的文件夹:

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 
    }) 
} 

换句话说,与filepath.Walk(),这里不应该有太多的“手动工作”。

+0

我认为'filepath.Walk()'是一个好主意,但我仍然需要复制'mkdirall'的内部来确定链中哪些文件夹不存在,请调用'mkdirall'来创建文件夹并然后使用'filepath.Walk()'遍历链并筛选第一个文件夹中收集的文件夹列表并调用'chown'。我认为与此相比,制作'mkdirall'的副本并添加一行来调用'chown'更加简单和容易理解。 – F21

+0

@ F21不,步行只适用于chown,而不是创建文件夹。你所要做的就是检查当前路径是否是一个文件夹,并且是'/ var/test1/test2/test3'的前缀:如果是,chown。如果不是,继续走。 – VonC

+0

作为另一个例子,假设'/ etc/lib /'已经存在,我想创建'/ etc/lib/test1/test2'。'test1'和'test2'也需​​要修改'uid'和'gid',但是我想离开'/ etc/lib'。在所有这些情况下,我不需要做一些处理来查看尚不存在的文件夹,请调用'mkdirall'来创建它们,然后使用'filepath.Walk()'的第一步中的信息来改变他们的'uid'和'gid'?否则,如果没有这些信息,我会更改已存在的父文件夹的所有者和组。 – F21

0

将mkdir进程切换到您希望为其创建目录的用户。这具有在单个命令中创建具有正确权限和所有权的目录的优点,而不是创建循环或背靠背运行多个命令。

实施例:

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() 

} 

由于子“MKDIR”运行作为由uid指定的用户时,文件夹将已经具有正确的所有者。如果你获得了正确的umask部分,每个目录也将具有正确的权限。

一个警告:这不是一个非常便携的解决方案。如果您确定您的代码只能在特定的操作系统上执行,那么使用系统调用应该只是您的解决方案。

相关问题