使用php将目录的全部内容复制到另一个目录

时间:2010-01-12 17:17:36

标签: php

我尝试使用

将目录的全部内容复制到另一个位置
copy ("old_location/*.*","new_location/");

但是它说找不到流,找不到真*.*

任何其他方式

由于 戴夫

16 个答案:

答案 0 :(得分:222)

似乎只复制 处理单个文件。这是我在this note上的copy documentation page中递归复制的函数:

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

答案 1 :(得分:86)

作为described here,这是另一种处理符号链接的方法:

/**
 * Copy a file, or recursively copy a folder and its contents
 * @author      Aidan Lister <aidan@php.net>
 * @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;
}

答案 2 :(得分:32)

copy()仅适用于文件。

DOS副本和Unix cp命令都将以递归方式复制 - 因此最快的解决方案就是外壳并使用它们。 e.g。

`cp -r $src $dest`;

否则你需要使用opendir / readdirscandir来读取目录的内容,遍历结果,如果is_dir为每个返回true,则递归进入它。

e.g。

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

答案 3 :(得分:21)

最好的解决方案是!

<?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
?>

答案 4 :(得分:12)

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

答案 5 :(得分:8)

与其他地方一样,copy仅适用于源文件而不是模式的单个文件。如果要按模式复制,请使用glob确定文件,然后运行复制。这不会复制子目录,也不会创建目标目录。

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

答案 6 :(得分:8)

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

从最后一行开始,这个

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

$destination ='b';

答案 7 :(得分:7)

非常感谢Felix Kling,感谢他在我的代码中使用过的优秀答案。我提供了一个布尔返回值的小增强来报告成功或失败:

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

答案 8 :(得分:5)

我修剪过的@Kzoty回答版本。 谢谢Kzoty。

用法

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

}

答案 9 :(得分:3)

使用Symfony,这很容易实现:

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

请参见https://symfony.com/doc/current/components/filesystem.html

答案 10 :(得分:1)

我通过SPL Directory Iterator克隆整个目录。

git fetch

答案 11 :(得分:1)

我遇到过类似的情况,我需要从一个域复制到同一服务器上的另一个域,这正是我的情况,您可以根据自己的需要进行调整:

foreach(glob('../folder/*.php') as $file) {
$adjust = substr($file,3);
copy($file, '/home/user/abcde.com/'.$adjust);

请注意使用“ substr()”,如果没有它,目标将变为“ /home/user/abcde.com/../folder/”,这可能是您不需要的。因此,我使用substr()消除了前3个字符(../),以获得所需的目标位置,即“ /home/user/abcde.com/folder/”。因此,您可以调整substr()函数以及glob()函数,直到满足您的个人需求为止。希望这会有所帮助。

答案 12 :(得分:1)

带有返回记录的长篇评论文章,基于此处大部分答案的一部分:

它是作为静态类方法呈现的,但也可以用作简单的函数:

/**
 * Recursive copy directories and content
 * 
 * @link        https://stackoverflow.com/a/2050909/591486
 * @since       4.7.2
*/
public static function copy_recursive( $source = null, $destination = null, &$log = [] ) {

    // is directory ##
    if ( is_dir( $source ) ) {

        $log[] = 'is_dir: '.$source;

        // log results of mkdir call ##
        $log[] = '@mkdir( "'.$destination.'" ): '.@mkdir( $destination );

        // get source directory contents ##
        $source_directory = dir( $source );

        // loop over items in source directory ##
        while ( FALSE !== ( $entry = $source_directory->read() ) ) {
            
            // skip hidden ##
            if ( $entry == '.' || $entry == '..' ) {

                $log[] = 'skip hidden entry: '.$entry;

                continue;

            }

            // get full source "entry" path ##
            $source_entry = $source . '/' . $entry; 

            // recurse for directories ##
            if ( is_dir( $source_entry ) ) {

                $log[] = 'is_dir: '.$source_entry;

                // return to self, with new arguments ##
                self::copy_recursive( $source_entry, $destination.'/'.$entry, $log );

                // break out of loop, to stop processing ##
                continue;

            }

            $log[] = 'copy: "'.$source_entry.'" --> "'.$destination.'/'.$entry.'"';

            // copy single files ##
            copy( $source_entry, $destination.'/'.$entry );

        }

        // close connection ##
        $source_directory->close();

    } else {

        $log[] = 'copy: "'.$source.'" --> "'.$destination.'"';

        // plain copy, as $destination is a file ##
        copy( $source, $destination );

    }

    // clean up log ##
    $log = array_unique( $log );

    // kick back log for debugging ##
    return $log;

}

呼叫方式:

// call method ##
$log = \namespace\to\method::copy_recursive( $source, $destination );

// write log to error file - you can also just dump it on the screen ##
error_log( var_export( $log, true ) );

答案 13 :(得分:0)

// using exec

function rCopy($directory, $destination)
{

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

    exec($command);

}

答案 14 :(得分:0)

对于Linux服务器,您只需要一行代码即可在保留权限的情况下递归复制:

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

另一种方法是:

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

但速度较慢,并且不保留权限。

答案 15 :(得分:0)

要将整个目录从一个目录复制到另一个目录,首先您应该确保传输的文件正确传输。为此,我们一一使用复制文件!在正确的目录中。我们复制一个文件并检查它是否为真转到下一个文件并继续...

1- 我使用此功能检查传输每个文件的安全过程:


function checksum($src,$dest)
{
    if(file_exists($src) and file_exists($dest)){
        return md5_file($src) == md5_file($dest) ? true : false;
    }else{
        return false;
    }
}

2- 现在我将文件从 src 一个一个复制到 dest,检查它然后继续。 (对于不想复制的文件夹,请使用排除数组)

$src  = __DIR__ . '/src';
$dest = __DIR__ . '/dest';
$exclude = ['.', '..'];

function copyDir($src, $dest, $exclude)
{

    !is_dir($dest) ? mkdir($dest) : '';

    foreach (scandir($src) as $item) {

        $srcPath = $src . '/' . $item;
        $destPath = $dest . '/' . $item;

        if (!in_array($item, $exclude)) {

            if (is_dir($srcPath)) {

                copyDir($srcPath, $destPath, $exclude);

            } else {

                copy($srcPath, $destPath);

                if (checksum($srcPath, $destPath)) {
                    echo 'Success transfer for:' . $srcPath . '<br>';
                }else{
                    echo 'Failed transfer for:' . $srcPath . '<br>';
                }
            }
        }
    }

}