将文件夹中的所有文件和文件夹移动到另一个文件夹中?

16

我想将文件夹中的所有文件和文件夹移动到另一个文件夹中。我找到了一个复制文件夹中所有文件到另一个文件夹的代码。 将文件夹中的所有文件移动到另一个文件夹

// Get array of all source files
$files = scandir("source");
// Identify directories
$source = "source/";
$destination = "destination/";
// Cycle through all source files
foreach ($files as $file) {
  if (in_array($file, array(".",".."))) continue;
  // If we copied this successfully, mark it for deletion
  if (copy($source.$file, $destination.$file)) {
    $delete[] = $source.$file;
  }
}
// Delete all successfully-copied files
foreach ($delete as $file) {
  unlink($file);
}

如何将此文件夹中的所有文件和文件夹移动到另一个文件夹中。


8个回答

34

这是我使用的东西

   // Function to remove folders and files 
    function rrmdir($dir) {
        if (is_dir($dir)) {
            $files = scandir($dir);
            foreach ($files as $file)
                if ($file != "." && $file != "..") rrmdir("$dir/$file");
            rmdir($dir);
        }
        else if (file_exists($dir)) unlink($dir);
    }

    // Function to Copy folders and files       
    function rcopy($src, $dst) {
        if (file_exists ( $dst ))
            rrmdir ( $dst );
        if (is_dir ( $src )) {
            mkdir ( $dst );
            $files = scandir ( $src );
            foreach ( $files as $file )
                if ($file != "." && $file != "..")
                    rcopy ( "$src/$file", "$dst/$file" );
        } else if (file_exists ( $src ))
            copy ( $src, $dst );
    }

使用方法

    rcopy($source , $destination );

另一个例子,不删除目标文件或文件夹

    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); 
    } 
请查看:http://php.net/manual/en/function.copy.php以获取更多精彩示例。
谢谢 :)

3
我知道这是一篇旧帖子,但是您是否需要使用DIRECTORY_SEPARATOR而不是'/'以实现系统兼容性? - Edgars Aivars

19

使用rename函数代替copy函数。

和同名的C语言函数不同,rename函数可以在不同的文件系统之间移动文件(自PHP 4.3.3版本开始支持Unix系统,自PHP 5.3.1版本开始支持Windows系统)。


1
感谢您抽出宝贵的时间回答问题...但我确定这与问题无关...您的答案仅适用于文件而不适用于文件夹。 - shaan gola
请注意,尝试从不同的磁盘(例如:从EC2到EFS)使用rename函数可能会导致PHP抛出“copy”错误,如此错误在此漏洞中所见:https://bugs.php.net/bug.php?id=54097 - Bing

12

12

你需要使用自定义函数:

Move_Folder_To("./path/old_folder_name",   "./path/new_folder_name"); 

函数代码:

function Move_Folder_To($source, $target){
    if( !is_dir($target) ) mkdir(dirname($target),null,true);
    rename( $source,  $target);
}

1
只有在父路径存在的情况下,此操作才能成功。例如rename("./path/old_folder_name", "./NEWpath/new_folder_name");是行不通的。在这种情况下,您应使用mkdir(dirname("./NEWpath/new_folder_name"), null, true);来创建该目录。 - Tobia

2

我认为对我来说答案还不够完整,因为没有在任何答案中定义DIRECTORY_SEPARATOR(感谢Edgar Aivars提醒我!),但我想写出我的解决方案,用于移动(重命名)、复制和删除目录结构(基于这篇文章的信息,感谢你的贡献!)。

defined('DS') ? NULL : define('DS',DIRECTORY_SEPARATOR);

function full_move($src, $dst){
    full_copy($src, $dst);
    full_remove($src);
}

function full_copy($src, $dst) {
    if (is_dir($src)) {
        @mkdir( $dst, 0777 ,TRUE);
        $files = scandir($src);
        foreach($files as $file){
            if ($file != "." && $file != ".."){
                full_copy("$src".DS."$file", "$dst".DS."$file");
            }
        }
    } else if (file_exists($src)){
        copy($src, $dst);
    }
}

function full_remove($dir) {
    if (is_dir($dir)) {
        $files = scandir($dir);
        foreach ($files as $file){
            if ($file != "." && $file != ".."){
                full_remove("$dir".DS."$file");
            }
        }
        rmdir($dir);
    }else if (file_exists($dir)){
        unlink($dir);
    }
}

我希望这能帮助任何人!(比如我未来的自己:D) 编辑:纠正拼写错误... :(

1
$src = 'user_data/company_2/T1/';
$dst = 'user_data/company_2/T2/T1/';

rcopy($src, $dst);  // Call function 
// Function to Copy folders and files       
function rcopy($src, $dst) {
    if (file_exists ( $dst ))
        rrmdir ( $dst );
    if (is_dir ( $src )) {
        mkdir ( $dst );
        $files = scandir ( $src );
        foreach ( $files as $file )
            if ($file != "." && $file != "..")
                rcopy ( "$src/$file", "$dst/$file" );

    } else if (file_exists ( $src ))
        copy ( $src, $dst );
                    rrmdir ( $src );
}       

// Function to remove folders and files 
function rrmdir($dir) {
    if (is_dir($dir)) {
        $files = scandir($dir);
        foreach ($files as $file)
            if ($file != "." && $file != "..") rrmdir("$dir/$file");
        rmdir($dir);
    }
    else if (file_exists($dir)) unlink($dir);
}

不错,这个代码可以正常运行,我不需要重构它 :) - Ifeanyi Amadi

1

经过数日的研究和查阅其他优秀的示例,我尝试编写了一个递归移动函数。

它提供了一个overwriteExisting选项。因此,如果overwriteExisting选项为false,文件将不会被移动,包含该文件的文件夹也不会被删除。

function moveRecursive($sourcePath, $targetPath, $overwriteExisting) {
    clearstatcache(); // not sure if this helps, or is even required.
    $dir = opendir($sourcePath);
    while (($file = readdir($dir)) !== false) {
        echo nl2br($file . "\n");
        if ($file != "." && $file != "..") {
            if (is_dir($sourcePath . "/" . $file) == true) {
                if (is_dir($targetPath. "/" . $file) == false) {
                    // I believe rename would be faster than copying and unlinking.
                    rename($sourcePath . "/" . $file, $targetPath. "/" . $file);
                } else {
                    moveRecursive($sourcePath . "/" . $file, $targetPath ."/" . $file, $overwriteExisting);
                    if ($files = glob($sourcePath . "/*")) {
                        // remove the empty directory.
                        if (@rmdir($sourcePath . "/" . $file) == false) {
                            echo nl2br("rmdir has not removed empty directory " . $sourcePath . "/" . $file . "\n");
                        }
                    } else {
                        // when overwriteExisting flag is false, there would be some files leftover.
                        echo nl2br("cannot remove. not empty, count = " . count(glob($sourcePath . "/*")) . " -> " . $sourcePath . "/" . $file . "\n");
                    }
                }
            } else {
                if (file_exists($targetPath. "/" . $file)) {
                    if ($overwriteExisting == true) {
                        // overwrite the file.
                        rename($sourcePath . "/" . $file, $targetPath. "/" . $file);
                    }
                } else {
                    // if the target file does not exist, simply move the file.
                    rename($sourcePath . "/" . $file, $targetPath. "/" . $file);
                }
            }
        }
    }
    closedir($dir);
}

我已经花了大约3个小时在许多不同的场景下进行测试,大部分时间都是有效的。然而,有时在Windows上会给我一个"Access denied code(5)"错误,这是我无法解决的。这就是为什么我在阅读了它的文档后把"clearstatcache()"函数放在了顶部。我不知道这是否是适当的使用方式。我肯定可以想象它会减慢函数的速度。
我也可以想象这种方法可能比"copy -> unlink"循环更快,因为如果目标子文件夹不存在,整个文件夹树下面的所有内容都会被移动。但是,我不确定并且没有经验来进行详尽的测试。

你应该得到10个赞,而不仅仅是一个。感谢你分享这种方法。 - user3934058

0

我使用它

// function used to copy full directory structure from source to target
function full_copy( $source, $target )
{
    if ( is_dir( $source ) )
    {
        mkdir( $target, 0777 );
        $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 );
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接