web-dev-qa-db-fra.com

Copier l'intégralité du contenu d'un répertoire dans un autre à l'aide de php

J'ai essayé de copier tout le contenu du répertoire dans un autre emplacement en utilisant 

copy ("old_location/*.*","new_location/");

mais il dit qu'il ne peut pas trouver le flux, true *.* n'est pas trouvé.

Tout autre moyen

Merci Dave

123
dave

Il semble que copier seulement traite fichiers uniques. Voici une fonction de copie récursive que j'ai trouvée dans cette note sur la page de documentation de copie :

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

Comme décrit ici , c'est une autre approche qui prend également en charge les liens symboliques:

/**
 * Copy a file, or recursively copy a folder and its contents
 * @author      Aidan Lister <[email protected]>
 * @version     1.0.1
 * @link        http://aidanlister.com/2004/04/recursively-copying-directories-in-php/
 * @param       string   $source    Source path
 * @param       string   $dest      Destination path
 * @param       int      $permissions New folder creation permissions
 * @return      bool     Returns true on success, false on failure
 */
function xcopy($source, $dest, $permissions = 0755)
{
    // 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, $permissions);
    }

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

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

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

copy () ne fonctionne qu'avec des fichiers.

La copie DOS et les commandes Unix cp seront toutes deux copiées de manière récursive. La solution la plus rapide consiste donc simplement à utiliser Shell. par exemple.

`cp -r $src $dest`;

Sinon, vous devrez utiliser la variable opendir/readdir ou scandir pour lire le contenu du répertoire, parcourir les résultats et si is_dir renvoie la valeur true pour chacun d'eux, effectuez une récurrence dans celui-ci.

par exemple.

function xcopy($src, $dest) {
    foreach (scandir($src) as $file) {
        if (!is_readable($src . '/' . $file)) continue;
        if (is_dir($src .'/' . $file) && ($file != '.') && ($file != '..') ) {
            mkdir($dest . '/' . $file);
            xcopy($src . '/' . $file, $dest . '/' . $file);
        } else {
            copy($src . '/' . $file, $dest . '/' . $file);
        }
    }
}
32
symcbean

La meilleure solution est!

<?php
$src = "/home/www/domain-name.com/source/folders/123456";
$dest = "/home/www/domain-name.com/test/123456";

Shell_exec("cp -r $src $dest");

echo "<H3>Copy Paste completed!</H3>"; //output when done
?>
21
black
function full_copy( $source, $target ) {
    if ( is_dir( $source ) ) {
        @mkdir( $target );
        $d = dir( $source );
        while ( FALSE !== ( $entry = $d->read() ) ) {
            if ( $entry == '.' || $entry == '..' ) {
                continue;
            }
            $Entry = $source . '/' . $entry; 
            if ( is_dir( $Entry ) ) {
                full_copy( $Entry, $target . '/' . $entry );
                continue;
            }
            copy( $Entry, $target . '/' . $entry );
        }

        $d->close();
    }else {
        copy( $source, $target );
    }
}
12
kzoty
<?php
    function copy_directory( $source, $destination ) {
        if ( is_dir( $source ) ) {
        @mkdir( $destination );
        $directory = dir( $source );
        while ( FALSE !== ( $readdirectory = $directory->read() ) ) {
            if ( $readdirectory == '.' || $readdirectory == '..' ) {
                continue;
            }
            $PathDir = $source . '/' . $readdirectory; 
            if ( is_dir( $PathDir ) ) {
                copy_directory( $PathDir, $destination . '/' . $readdirectory );
                continue;
            }
            copy( $PathDir, $destination . '/' . $readdirectory );
        }

        $directory->close();
        }else {
        copy( $source, $destination );
        }
    }
?>

à partir de la 4ème ligne, faites ceci

$source = 'wordpress';//i.e. your source path

et

$destination ='b';
8
Hemanta Nandi

Comme indiqué ailleurs, copy ne fonctionne qu'avec un seul fichier pour la source et non un modèle. Si vous souhaitez copier par modèle, utilisez glob pour déterminer les fichiers, puis exécutez la copie. Cela ne copie pas les sous-répertoires et ne crée pas le répertoire de destination.

function copyToDir($pattern, $dir)
{
    foreach (glob($pattern) as $file) {
        if(!is_dir($file) && is_readable($file)) {
            $dest = realpath($dir . DIRECTORY_SEPARATOR) . basename($file);
            copy($file, $dest);
        }
    }    
}
copyToDir('./test/foo/*.txt', './test/bar'); // copies all txt files
7
Gordon

Merci à Felix Kling pour son excellente réponse que j’ai utilisée avec reconnaissance dans mon code. J'offre une petite amélioration d'une valeur de retour booléenne pour signaler un succès ou un échec:

function recurse_copy($src, $dst) {

  $dir = opendir($src);
  $result = ($dir === false ? false : true);

  if ($result !== false) {
    $result = @mkdir($dst);

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

  return $result;
}
7
gonzo

Ma version taillée de @Kzoty répond ..__ Merci Kzoty.

Usage

Helper::copy($sourcePath, $targetPath);

class Helper {

    static function copy($source, $target) {
        if (!is_dir($source)) {//it is a file, do a normal copy
            copy($source, $target);
            return;
        }

        //it is a folder, copy its files & sub-folders
        @mkdir($target);
        $d = dir($source);
        $navFolders = array('.', '..');
        while (false !== ($fileEntry=$d->read() )) {//copy one by one
            //skip if it is navigation folder . or ..
            if (in_array($fileEntry, $navFolders) ) {
                continue;
            }

            //do copy
            $s = "$source/$fileEntry";
            $t = "$target/$fileEntry";
            self::copy($s, $t);
        }
        $d->close();
    }

}
5
Nam G VU

Avec Symfony, cela est très facile à accomplir:

$fileSystem = new Symfony\Component\Filesystem\Filesystem();
$fileSystem->mirror($from, $to);

Voir https://symfony.com/doc/current/components/filesystem.html

3
chickenchilli

Je clone tout le répertoire par SPL Directory Iterator. 

function recursiveCopy($source, $destination)
{
    if (!file_exists($destination)) {
        mkdir($destination);
    }

    $splFileInfoArr = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);

    foreach ($splFileInfoArr as $fullPath => $splFileinfo) {
        //skip . ..
        if (in_array($splFileinfo->getBasename(), [".", ".."])) {
            continue;
        }
        //get relative path of source file or folder
        $path = str_replace($source, "", $splFileinfo->getPathname());

        if ($splFileinfo->isDir()) {
            mkdir($destination . "/" . $path);
        } else {
        copy($fullPath, $destination . "/" . $path);
        }
    }
}
#calling the function
recursiveCopy(__DIR__ . "/source", __DIR__ . "/destination");
1
Tuhin Bepari

Pour les serveurs Linux, vous n'avez besoin que d'une ligne de code pour copier de manière récursive tout en préservant les droits:

exec('cp -a '.$source.' '.$dest);

Une autre façon de le faire est:

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

mais c'est plus lent et ne conserve pas les autorisations.

0
Dan Bray
// using exec

function rCopy($directory, $destination)
{

    $command = sprintf('cp -r %s/* %s', $directory, $destination);

    exec($command);

}
0
Łukasz Szpak