chmod 对数千个文件的递归权限

Tit*_*umi 16 permissions chmod recursive

这是一个关于递归地“chmoding”的更普遍的问题。

我有这个脚本,它在某些时候需要在一个包含几十万个文件的文件夹中递归更改权限。每天都会在该文件夹中添加新文件,但是已经存在的文件已经设置了权限并且不会更改。

我的问题是......当我打电话时

chmod 775。-R

它是尝试为已经设置了正确权限的文件设置权限,还是只为没有正确权限的新文件设置权限?

似乎总是需要很长时间才能在脚本中通过此命令,即使“新”文件只有几千个并且应该很快完成它们的权限。

我已经查看了 chmod 的手册页,但它似乎没有提到关于这种情况的任何内容。

如果 chmod 没有事先检查权限,我应该开始考虑将 'find' 与 'chmod' 结合起来吗?

Hau*_*ing 10

查找/chmod 优化

双方find并chmod要读

  1. 所有目录条目
  2. 所有这些条目的 inode

您可能会通过首先读取所有条目然后读取所有 inode(在旋转磁盘上)来提高性能,因为这样磁盘磁头就不会在目录和 inode 之间移动)。由于chmod 是愚蠢的(如其他答案的人解释),应当通过所谓的find只。但即便如此,在第一个被写入之前读取所有 inode 可能会有所帮助(假设您有足够的空闲 RAM 用于磁盘缓存)。我建议这样做:

find . -printf "" # reading the file names only
find . ! -perm 775 -printf "" # reading all the inodes (file names are cached)
find . ! -perm 775 -exec chmod 775 + # writing to the cache without reading from disk
Run Code Online (Sandbox Code Playgroud)

好的解决方案:ACL

好的解决方案可能完全不同:如果文件是在这个目录中创建的(而不是从其他地方移动),那么 ACL 可以即时完成这项工作。您只需在父目录上设置默认 ACL。

文件系统优化可以进一步改进。如果是 ext3/ext4 那么你可能会e2fsck -D不时运行。也许把这个目录放到一个单独的卷上会有所帮助。您可以尝试不同的文件系统或文件系统设置(例如不同的 inode 大小)。


mrb*_*mrb 9

chmod可能会或可能不会更改已设置为您想要的文件的权限,但如果没有,它仍然需要检查它们以查看它们当前的权限是什么[0]。有数十万个文件,我认为这两种方式都不重要;时间很可能花在stat每个文件的工具上。

您可以尝试使用find来检查比上次运行更新的文件或需要运行的文件chmod,但我认为您不会获得太大的速度改进。

如果您的脚本可能,您可以先将新文件放入一个单独的目录中,作为“保存”区域。然后你可以在chmod那个目录(只有新文件),然后mv把它们和其他的放在一起。这应该会快得多,但不幸的是不适用于每个应用程序。

[0] 即使它确实尝试设置不需要任何更改的文件的权限,底层文件系统也可能不会对请求做任何事情,因为它是不必要的。


Ric*_*chm 9

假设在 Ubuntu 12.10 上使用chmod来自GNU coreutils 包。

chmod 775 . -Rfchmodat无论权限是否需要更改,它都会为它找到的每个文件执行系统调用。我通过检查代码并使用strace chmod 775 . -R(下面的代码段)列出实际行为来确认这一点。

newfstatat(4, "d", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "d", 0775)                  = 0
newfstatat(4, "c", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "c", 0775)                  = 0
newfstatat(4, "a", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "a", 0775)                  = 0
newfstatat(4, "b", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "b", 0775)                  = 0
Run Code Online (Sandbox Code Playgroud)

fchmodat在每个文件上运行有几个缺点

  • 如果更改了大量文件,则额外的系统调用可能会变得很重要。该find/ xargs/chmod其他人所说的方法将有可能只改变这种需要更改文件更快。
  • 调用fchmodat更改每个文件的文件状态修改 (ctime)。这将导致每个文件/inode 每次都更改,并可能导致过多的磁盘写入。可以使用挂载选项来停止这些多余的写入。

一个简单的实验显示了直接发生的 ctime 变化 chmod

auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 d
auser@duncow:/tmp/blah.test$ chmod 775 . -R
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d
Run Code Online (Sandbox Code Playgroud)

但是,这并不为改变find/ xargs/chmod几分钟后

auser@duncow:/tmp/blah.test$ date
Tue Jun 18 18:27:27 BST 2013
auser@duncow:/tmp/blah.test$ find . ! -perm 775 -print0 | xargs -0 -I {} chmod 775 {}
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d
Run Code Online (Sandbox Code Playgroud)

我总是倾向于使用find/ xargs/chmod因为发现给出了选择的东西更多的控制版本。