2011-04-18 10 views
16

En mi antiguo VPS estaba usando el siguiente código para copiar los archivos y directorios dentro de un directorio a un nuevo directorio que se creó después de que el usuario envió su formulario.Copia recursiva del directorio

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") 

Sin embargo, ahora en mi nuevo VPS solo creará el directorio principal, pero no copiará ninguno de los archivos en él. No entiendo lo que podría haber cambiado entre los 2 VPS.

+0

Su código sería más fácil de leer si sangría cada bloque. –

+0

Puede ser la versión de PHP, pruebe esta función [copia recursiva] (http://www.php.net/manual/en/function.copy.php#91256) del manual php. – SIFE

+0

SIFE - Intenté ese y tampoco funcionó. Entonces no estoy seguro de lo que estoy haciendo mal. Pero solo copio el código, ingreso mis rutas de origen y de destino, y me aseguro de que chmod esté configurado, pero aún no funciona – Jason

Respuesta

7

Podría sugerir que (suponiendo que sea un * VX de nix) simplemente haga una llamada al sistema al cp -r y deje que haga la copia por usted.

0

Supongo que debe verificar el usuario (grupo) derechos. Debería considerar chmod por ejemplo, dependiendo de cómo ejecuta (su?) PHP. También puede optar por modificar su configuración de php.

67

Pruebe algo como esto:

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

iterador iterar a través de todas las carpetas y subcarpetas y hacer copia de archivos desde $source a $dest

+0

Si está usando Zend Guard, asegúrese de usar $ iterator-> getSubPathName() para llamarlo como un función anónima. Lo que funcionó para mí fue: call_user_func_array (array ($ iterator, "getSubPathName"), array()); – Someone13

+0

Gracias OzzyCzech Escritura muy útil para ... pero también quiero hacer una copia de seguridad de mi base de datos con amabilidad. Cuénteme sobre ese proceso o escriba una secuencia de comandos o proporcióneme cualquier enlace para esa –

+0

¡Está funcionando! upvoted –

5

Esto es lo que utilizamos en nuestra empresa:

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

Necesita agregar if (! File_exists ($ dest. "/". $ sourcefolder)) comprobar antes de mkdir ($ dest. "/". $ sourcefolder); en los casos en que existen carpetas –

8

He cambiado el código de Joseph (abajo), porque no funcionaba para mí. Esto es lo que funciona:

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] añaden prueba antes de la creación de un directorio (línea 7)

+0

Este script aún no funciona (en mi caso). – Armin

2

Esta carpeta copias función recursivley muy sólido. He copiado desde la sección de comentarios en 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); 
} 
+0

Funcionó para mí :) –

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

OzzyCheck de es elegante y original, pero se olvidó del mkdir inicial ($ dest); Ver a continuación. Ningún comando de copia se proporciona con contenido solamente. Debe cumplir su rol completo.

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

El Symfony's FileSystem Component ofrece un buen control de errores, así como eliminar recursiva y las demás cosas útiles. Usando @ gran respuesta de OzzyCzech, podemos hacer un robusto copia recursiva de esta manera:

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

Nota: puede utilizar este componente, así como todos los demás componentes de Symfony2 independiente.

0

hmm.como eso es complicado))

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 - algo como que www/folder/ahah/file.txt

0

He aquí una función recursiva sencilla para copiar directorios enteros

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

¿Por qué no simplemente hacer que el OS para cuidar de esto?

system("cp -r olddir newdir"); 

Listo.

+0

Bienvenido a SO. Por favor, formatee su código correctamente. –

+6

Votación baja porque este es un código dependiente del sistema operativo – paulus

+0

No solo depende del sistema operativo, sino que la llamada al "sistema" generalmente está deshabilitada en la producción. – user2716262

0

Hubo algunos problemas con las funciones que probé en el hilo y aquí hay una poderosa función que cubre todo. Lo más destacado:

  1. No hay necesidad de tener un directorios de origen inicial o intermedia. Se manejarán todos los directorios hasta el directorio de origen y los directorios copiados.

  2. Posibilidad de saltear el directorio o los archivos de una matriz. (opcional) Con el global $skip; se omiten los archivos incluso en los directorios de nivel secundario.

  3. Soporte recursivo completo, todos los archivos y directorios en múltiples profundidades son compatibles.

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

/** 
* code by Nk ([email protected]) 
*/ 

class filesystem 
{ 
    public static function normalizePath($path) 
    { 
     return $path.(is_dir($path) && !preg_match('@/[email protected]', $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'); ?> 
Cuestiones relacionadas