Recursive Copy of Directory

别来无恙 提交于 2019-11-28 06:53:05
OzzyCzech

Try something like this:

$source = "dir/dir/dir";
$dest= "dest/dir";

mkdir($dest, 0755);
foreach (
 $iterator = new \RecursiveIteratorIterator(
  new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS),
  \RecursiveIteratorIterator::SELF_FIRST) as $item
) {
  if ($item->isDir()) {
    mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
  } else {
    copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
  }
}

Iterator iterate through all folders and subfolders and make copy of files from $source to $dest

Could I suggest that (assuming it's a *nix VPS) that you just do a system call to cp -r and let that do the copy for you.

Belovoj

I have changed Joseph's code (below), because it wasn't working for me. This is what works:

function cpy($source, $dest){
    if(is_dir($source)) {
        $dir_handle=opendir($source);
        while($file=readdir($dir_handle)){
            if($file!="." && $file!=".."){
                if(is_dir($source."/".$file)){
                    if(!is_dir($dest."/".$file)){
                        mkdir($dest."/".$file);
                    }
                    cpy($source."/".$file, $dest."/".$file);
                } else {
                    copy($source."/".$file, $dest."/".$file);
                }
            }
        }
        closedir($dir_handle);
    } else {
        copy($source, $dest);
    }
}

[EDIT] added test before creating a directory (line 7)

The Symfony's FileSystem Component offers a good error handling as well as recursive remove and other useful stuffs. Using @OzzyCzech's great answer, we can do a robust recursive copy this way:

use Symfony\Component\Filesystem\Filesystem;

// ...

$fileSystem = new FileSystem();

if (file_exists($target))
{
    $this->fileSystem->remove($target);
}

$this->fileSystem->mkdir($target);

$directoryIterator = new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($directoryIterator, \RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $item)
{
    if ($item->isDir())
    {
        $fileSystem->mkdir($target . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
    }
    else
    {
        $fileSystem->copy($item, $target . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
    }
}

Note: you can use this component as well as all other Symfony2 components standalone.

Here's what we use at our company:

static public function copyr($source, $dest)
{
    // recursive function to copy
    // all subdirectories and contents:
    if(is_dir($source)) {
        $dir_handle=opendir($source);
        $sourcefolder = basename($source);
        mkdir($dest."/".$sourcefolder);
        while($file=readdir($dir_handle)){
            if($file!="." && $file!=".."){
                if(is_dir($source."/".$file)){
                    self::copyr($source."/".$file, $dest."/".$sourcefolder);
                } else {
                    copy($source."/".$file, $dest."/".$file);
                }
            }
        }
        closedir($dir_handle);
    } else {
        // can also handle simple copy commands
        copy($source, $dest);
    }
}

This function copies folder recursivley very solid. I've copied it from the comments section on copy command of php.net

function recurse_copy($src,$dst) { 
    $dir = opendir($src); 
    @mkdir($dst); 
    while(false !== ( $file = readdir($dir)) ) { 
        if (( $file != '.' ) && ( $file != '..' )) { 
            if ( is_dir($src . '/' . $file) ) { 
                recurse_copy($src . '/' . $file,$dst . '/' . $file); 
            } 
            else { 
                copy($src . '/' . $file,$dst . '/' . $file); 
            } 
        } 
    } 
    closedir($dir); 
}

OzzyCheck's is elegant and original, but he forgot the initial mkdir($dest); See below. No copy command is ever provided with contents only. It must fulfill its entire role.

$source = "dir/dir/dir";
$dest= "dest/dir";

mkdir($dest, 0755);
foreach (
  $iterator = new RecursiveIteratorIterator(
  new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
  RecursiveIteratorIterator::SELF_FIRST) as $item) {
  if ($item->isDir()) {
    mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
  } else {
    copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
  }
}
exiang
function recurse_copy($source, $dest)
{
    // Check for symlinks
    if (is_link($source)) {
        return symlink(readlink($source), $dest);
    }

    // Simple copy for a file
    if (is_file($source)) {
        return copy($source, $dest);
    }

    // Make destination directory
    if (!is_dir($dest)) {
        mkdir($dest);
    }

    // Loop through the folder
    $dir = dir($source);
    while (false !== $entry = $dir->read()) {
        // Skip pointers
        if ($entry == '.' || $entry == '..') {
            continue;
        }

        // Deep copy directories
        recurse_copy("$source/$entry", "$dest/$entry");
    }

    // Clean up
    $dir->close();
    return true;
}

Here's a simple recursive function to copy entire directories

source: http://php.net/manual/de/function.copy.php

<?php 
function recurse_copy($src,$dst) { 
    $dir = opendir($src); 
    @mkdir($dst); 
    while(false !== ( $file = readdir($dir)) ) { 
        if (( $file != '.' ) && ( $file != '..' )) { 
            if ( is_dir($src . '/' . $file) ) { 
                recurse_copy($src . '/' . $file,$dst . '/' . $file); 
            } 
            else { 
                copy($src . '/' . $file,$dst . '/' . $file); 
            } 
        } 
    } 
    closedir($dir); 
} 
?>

I guess you should check user(group)rights. You should consider chmod for example, depending on how you run (su?)PHP. You could possibly also choose to modify your php configuration.

hmm. as that's complicated ))

function mkdir_recursive( $dir ){
  $prev = dirname($dir);
  if( ! file_exists($prev))
  {
    mkdir_recursive($prev);
  }
  if( ! file_exists($dir))
  {
     mkdir($dir);
  }
}

...

foreach( $files as $file){
  mkdir_recursive( dirname( $dir_d . $file));
  copy( $dir_s . $file, $dir_d . $file);
}

$file - somthing like that www/folder/ahah/file.txt

William

Why not just ask the OS to take care of this?

system("cp -r olddir newdir");

Done.

There were some issues with the functions that I tested in the thread and here is a powerful function that covers everything. Highlights:

  1. No need to have an initial or intermediate source directories. All of the directories up to the source directory and to the copied directories will be handled.

  2. Ability to skip directory or files from an array. (optional) With the global $skip; skipping of files even under sub level directories are handled.

  3. Full recursive support, all the files and directories in multiple depth are supported.

$from = "/path/to/source_dir";
$to = "/path/to/destination_dir";
$skip = array('some_file.php', 'somedir');

copy_r($from, $to, $skip);

function copy_r($from, $to, $skip=false) {
    global $skip;
    $dir = opendir($from);
    if (!file_exists($to)) {mkdir ($to, 0775, true);}
    while (false !== ($file = readdir($dir))) {
        if ($file == '.' OR $file == '..' OR in_array($file, $skip)) {continue;}

        if (is_dir($from . DIRECTORY_SEPARATOR . $file)) {
            copy_r($from . DIRECTORY_SEPARATOR . $file, $to . DIRECTORY_SEPARATOR . $file);
        }
        else {
            copy($from . DIRECTORY_SEPARATOR . $file, $to . DIRECTORY_SEPARATOR . $file);
        }
    }
    closedir($dir);
}
<?php

/**
 * code by Nk (nk.have.a@gmail.com)
 */

class filesystem
{
    public static function normalizePath($path)
    {
        return $path.(is_dir($path) && !preg_match('@/$@', $path) ? '/' : '');      
    }

    public static function rscandir($dir, $sort = SCANDIR_SORT_ASCENDING)
    {
        $results = array();

        if(!is_dir($dir))
        return $results;

        $dir = self::normalizePath($dir);

        $objects = scandir($dir, $sort);

        foreach($objects as $object)
        if($object != '.' && $object != '..')
        {
            if(is_dir($dir.$object))
            $results = array_merge($results, self::rscandir($dir.$object, $sort));
            else
            array_push($results, $dir.$object);
        }

        array_push($results, $dir);

        return $results;
    }

    public static function rcopy($source, $dest, $destmode = null)
    {
        $files = self::rscandir($source);

        if(empty($files))
        return;

        if(!file_exists($dest))
        mkdir($dest, is_int($destmode) ? $destmode : fileperms($source), true);

        $source = self::normalizePath(realpath($source));
        $dest = self::normalizePath(realpath($dest));

        foreach($files as $file)
        {
            $file_dest = str_replace($source, $dest, $file);

            if(is_dir($file))
            {
                if(!file_exists($file_dest))
                mkdir($file_dest, is_int($destmode) ? $destmode : fileperms($file), true);
            }
            else
            copy($file, $file_dest);
        }
    }
}

?>

/var/www/websiteA/backup.php :

<?php /* include.. */ filesystem::rcopy('/var/www/websiteA/', '../websiteB'); ?>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!