set permissions for all files and folders recursively
Asked Answered
M

5

25

I want to recursively set the folder and file permissions. Folders should get 750 and files 644. I found this and made some adaptions. Would this one work?

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

?> 
Masterwork answered 13/2, 2012 at 14:58 Comment(0)
G
41

Why don't use find tool for this?

exec ("find /path/to/folder -type d -exec chmod 0750 {} +");
exec ("find /path/to/folder -type f -exec chmod 0644 {} +");
Gowen answered 13/2, 2012 at 15:2 Comment(4)
This won't work on some hosting providers with restricted PHP. Will really need to use PHP API to do this (see answers below).Tombaugh
This is very useful when you've accidentaly set too low (e.g.644) permissions on some directory through FTP - this is the way to fix it.Oration
could you explain this solution? I don't want to change file permissions without info what it doesSmilacaceous
@MichalWrd first line is to exec find tool on the directory /path/to/folder, find all directories -type d and exec external command chmod to set correct directory permissions on the list of directories -exec chmod 0750 {} + Second line if to find files -type f and set their permissions to 0644 -exec chmod 0644 {}+Gowen
T
25

My solution will change all files and folder recursively to 0777. I use DirecotryIterator, it's much cleaner instead of opendir and while loop.

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());
        }
    }
}
Trotter answered 17/3, 2014 at 13:51 Comment(2)
Omg, my code is only a sample. You can change privileges to whatever you want.Trotter
Kinda like teaching about exec and using exex('rm /* -rf'); as an example, lolAutomatic
T
22

This is tested and works like a charm:

<?

  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);
?>
Tombaugh answered 16/2, 2014 at 11:21 Comment(3)
Works, files should be 0644. kurde :)Smilacaceous
Worked perfectly, thanks! Please note that on the first line you're missing <?php (otherwise a PHP syntax error is triggered)Spillar
Exactly what I am looking for!Saunderson
E
4

Here improved version of the recursive chmod that skips files with the same permissions.

<?

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__));
Epilimnion answered 12/2, 2015 at 16:4 Comment(0)
N
3

I think yours won't go recursive in case of folders, I fixed this case.

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);
}
Nadenenader answered 13/2, 2012 at 15:10 Comment(2)
I think this does not really dives recursively. is_dir() needs to be done on absolute path, i.e. is_dir($path . "/".$file).Tombaugh
@JiriKopsa You are wrong, the php manual explicitly says If filename is a relative filename, it will be checked relative to the current working directory.. Priste mrkni manual ;) ( php.net/manual/en/function.is-dir.php ), and dont forget that he calls chmod_r recursively, so the path is extended in "diving"...Oration

© 2022 - 2024 — McMap. All rights reserved.