Рекурсивная копия каталога

На моем старом VPS я использовал следующий код для копирования файлов и каталогов в каталоге в новый каталог, созданный после того, как пользователь отправил свою форму.

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

   // Make destination directory
   if (!is_dir($dest)) {
      mkdir($dest);
      $company = ($_POST['company']);
   }

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

      // Deep copy directories
      if ($dest !== "$source/$entry") {
         copyr("$source/$entry", "$dest/$entry");
      }
   }

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

copyr('Template/MemberPages', "Members/$company")

Однако теперь на моем новом VPS будет создан только основной каталог, но он не будет копировать ни один из файлов на него. Я не понимаю, что могло измениться между 2 VPS?

Ответы

Ответ 1

Попробуйте что-то вроде этого:

$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());
  }
}

Итератор выполняет итерацию по всем папкам и подпапкам и делает копию файлов с $source до $dest

Ответ 2

Я изменил код Джозефа (ниже), потому что он не работал у меня. Это то, что работает:

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] добавлен тест перед созданием каталога (строка 7)

Ответ 3

Могу ли я предположить, что (при условии, что это Vix Vix), что вы просто выполняете системный вызов cp -r, и пусть это сделает для вас копию.

Ответ 4

Вот что мы используем в нашей компании:

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

Ответ 5

Symfony FileSystem Component предлагает хорошую обработку ошибок, а также рекурсивное удаление и другие полезные материалы. Используя отличный ответ @OzzyCzech, мы можем сделать надежную рекурсивную копию следующим образом:

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

Примечание. Вы можете использовать этот компонент, а также все остальные компоненты Symfony2 автономно.

Ответ 6

Эта функция копирует папку recursivley очень прочную. Я скопировал его из раздела комментариев в скопировать команду 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); 
}

Ответ 7

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

Ответ 8

OzzyCheck элегантен и оригинален, но он забыл начальный mkdir ($ dest); Смотри ниже. Команда копирования никогда не предоставляется только содержимым. Он должен выполнять всю свою роль.

$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());
  }
}

Ответ 9

Я думаю, вы должны проверить пользователя (группу) права. Вы должны рассмотреть chmod, например, в зависимости от того, как вы запускаете (su?) PHP. Возможно, вы также захотите изменить конфигурацию php.

Ответ 10

хмм. как это сложно))

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 - нечто подобное www/folder/ahah/file.txt

Ответ 11

Здесь простая рекурсивная функция для копирования целых каталогов

источник: 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); 
} 
?>

Ответ 12

Почему бы просто не попросить ОС позаботиться об этом?

system("cp -r olddir newdir");

Готово.

Ответ 13

Были некоторые проблемы с функциями, которые я тестировал в потоке, и вот мощная функция, которая охватывает все. Основные характеристики:

  • Не нужно иметь исходные или промежуточные исходные каталоги. Все каталоги до исходного каталога и скопированных каталогов будут обрабатываться.

  • Возможность пропустить каталог или файлы из массива. (необязательно) С global $skip; выполняется передача файлов даже под каталоги на уровне юниверса.

  • Полная рекурсивная поддержка, поддерживаются все файлы и каталоги с несколькими глубинами.

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