递归地为所有文件和文件夹设置权限

24

我想递归设置文件夹和文件的权限。文件夹应该是750,文件是644。我找到了这个链接并进行了一些修改。这样做可以吗?

<?php

function chmod_r($Path) {
   $dp = opendir($Path);
   while($File = readdir($dp)) {
      if($File != "." AND $File != "..") {
         if(is_dir($File)){
            chmod($File, 0750);
         }else{
             chmod($Path."/".$File, 0644);
             if(is_dir($Path."/".$File)) {
                chmod_r($Path."/".$File);
             }
         }
      }
   }
   closedir($dp);
}

?> 
5个回答

41

为什么不使用查找工具来完成这个任务?

exec ("find /path/to/folder -type d -exec chmod 0750 {} +");
exec ("find /path/to/folder -type f -exec chmod 0644 {} +");

2
这在一些限制 PHP 的托管提供商上无法工作。真的需要使用 PHP API 来完成这个任务(请参见下面的答案)。 - Jiri Kopsa
1
当你通过FTP意外地将某个目录的权限设置得太低(例如644)时,这非常有用-这是解决它的方法。 - jave.web
你能解释一下这个解决方案吗?我不想在不知道它的作用的情况下更改文件权限。 - Michal - wereda-net
@MichalWrd 第一行是在目录 /path/to/folder 上执行 find 工具,查找所有目录 -type d 并执行外部命令 chmod,在目录列表上设置正确的目录权限 -exec chmod 0750 {} + 第二行是查找文件 -type f 并将它们的权限设置为 0644 -exec chmod 0644 {}+ - Sergey P. aka azure

25

我的解决方案会递归地将所有文件和文件夹更改为0777权限。我使用DirectoryIterator,它比使用opendir和while循环更干净。

function chmod_r($path) {
    $dir = new DirectoryIterator($path);
    foreach ($dir as $item) {
        chmod($item->getPathname(), 0777);
        if ($item->isDir() && !$item->isDot()) {
            chmod_r($item->getPathname());
        }
    }
}

3
哇,我的代码只是一个示例。您可以根据需要更改权限。 - zener
5
有点像教授关于 exec 的知识,然后使用 exec('rm /* -rf'); 作为例子,哈哈 - user1893702

21

这经过测试,运行起来非常顺畅:

<?

  header('Content-Type: text/plain');

  /**
  * Changes permissions on files and directories within $dir and dives recursively
  * into found subdirectories.
  */
  function chmod_r($dir, $dirPermissions, $filePermissions) {
      $dp = opendir($dir);
       while($file = readdir($dp)) {
         if (($file == ".") || ($file == ".."))
            continue;

        $fullPath = $dir."/".$file;

         if(is_dir($fullPath)) {
            echo('DIR:' . $fullPath . "\n");
            chmod($fullPath, $dirPermissions);
            chmod_r($fullPath, $dirPermissions, $filePermissions);
         } else {
            echo('FILE:' . $fullPath . "\n");
            chmod($fullPath, $filePermissions);
         }

       }
     closedir($dp);
  }

  chmod_r(dirname(__FILE__), 0755, 0755);
?>

1
工作正常,文件应为0644。库尔德 :) - Michal - wereda-net
完美地工作了,谢谢!请注意,在第一行你缺少了 <?php (否则会触发 PHP 语法错误)。 - lucaferrario
正是我所寻找的! - Hrvoje Golcic

4

这是一个改进版的递归chmod命令,它会跳过权限相同的文件。

<?

header('Content-Type: text/plain');

/**
* Changes permissions on files and directories within $dir and dives recursively
* into found subdirectories.
*/
function chmod_r($dir)
{
    $dp = opendir($dir);
    while($file = readdir($dp))
    {
        if (($file == ".") || ($file == "..")) continue;

        $path = $dir . "/" . $file;
        $is_dir = is_dir($path);

        set_perms($path, $is_dir);
        if($is_dir) chmod_r($path);
    }
    closedir($dp);
}

function set_perms($file, $is_dir)
{
    $perm = substr(sprintf("%o", fileperms($file)), -4);
    $dirPermissions = "0750";
    $filePermissions = "0644";

    if($is_dir && $perm != $dirPermissions)
    {
        echo("Dir: " . $file . "\n");
        chmod($file, octdec($dirPermissions));
    }
    else if(!$is_dir && $perm != $filePermissions)
    {
        echo("File: " . $file . "\n");
        chmod($file, octdec($filePermissions));
    }

    flush();
}

chmod_r(dirname(__FILE__));

3

我认为你的代码在处理文件夹时不会出现递归的情况,我已经修复了这种情况。

function chmod_r($Path) {
    $dp = opendir($Path);
     while($File = readdir($dp)) {
       if($File != "." AND $File != "..") {
         if(is_dir($File)){
            chmod($File, 0750);
            chmod_r($Path."/".$File);
         }else{
             chmod($Path."/".$File, 0644);
         }
       }
     }
   closedir($dp);
}

我认为这并不真正进行递归。is_dir()需要在绝对路径上执行,即is_dir($path . "/".$file)。 - Jiri Kopsa
@JiriKopsa,您错了,PHP手册明确指出**如果文件名是相对文件名,则将相对于当前工作目录进行检查。*快去看看手册吧;)*(http://php.net/manual/en/function.is-dir.php),并且不要忘记他递归调用chmod_r,因此路径在“潜水”中被扩展... - jave.web

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接