15

I want to move all files and folders inside a folder to another folder. I found a code to copy all files inside a folder to another folder. move all files in a folder to another

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

How do I change this to move all folders and files inside this folder to another folder.

Community
  • 1
  • 1
Sara
  • 14,098
  • 13
  • 34
  • 50
  • possible duplicate of [Copy all files and folder from one directory to another directory PHP](http://stackoverflow.com/questions/1513618/copy-all-files-and-folder-from-one-directory-to-another-directory-php) – Jan Hančič Mar 23 '12 at 07:30

8 Answers8

33

This is what i use

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

Usage

    rcopy($source , $destination );

Another example without deleting destination file or folder

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

Please See: http://php.net/manual/en/function.copy.php for more juicy examples

Thanks :)

Baba
  • 94,024
  • 28
  • 166
  • 217
  • 3
    I know this is old post but still - dont you need to use DIRECTORY_SEPARATOR instead of '/' for system compatibility? – Edgars Aivars Feb 01 '18 at 11:54
19

Use rename instead of copy.

Unlike the C function with the same name, rename can move a file from one file system to another (since PHP 4.3.3 on Unix and since PHP 5.3.1 on Windows).

Joni
  • 108,737
  • 14
  • 143
  • 193
  • 1
    Thanks for giving your precious time to answer for the problem ...but i sure it is not relevant with the issue ..your answer only work for **files** and not for folder. – shaan gola Aug 03 '17 at 06:48
  • Beware is trying to use `rename` from different disks (ex: EC2 to EFS) as PHP will throw a "copy" error as seen in this bug: https://bugs.php.net/bug.php?id=54097 – Bing Jun 13 '20 at 21:03
12

You need the custom function:

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

function code:

function Move_Folder_To($source, $target){
    if( !is_dir($target) ) mkdir(dirname($target),null,true);
    rename( $source,  $target);
}
T.Todua
  • 53,146
  • 19
  • 236
  • 237
  • 1
    This work only if the parent path exists. For example `rename( "./path/old_folder_name", "./NEWpath/new_folder_name" );` doesn't work. In this case you should create the dir with `mkdir(dirname("./NEWpath/new_folder_name"),null,true);` – Tobia May 23 '18 at 15:04
12

Think this should do the trick: http://php.net/manual/en/function.shell-exec.php

shell_exec("mv sourcedirectory path_to_destination");

Hope this help.

Sebas
  • 21,192
  • 9
  • 55
  • 109
metalfight - user868766
  • 2,722
  • 1
  • 16
  • 20
2

I think the answers are not complete for me, beacuse DIRECTORY_SEPARATOR are not defined on any answer (thans to Edgar Aivars for remember that!), but I want to write my solution for move (rename), copy and delete directory structures (based on this post info, the credits are for yours!).

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

I hope this hepls anyone! (lile me in the future :D )

EDIT: Spell corrections... :(

chybeat
  • 36
  • 6
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);
}
josliber
  • 43,891
  • 12
  • 98
  • 133
Neeraj
  • 11
  • 1
1

My attempt at a recursive move function, after days of research and going through other excellent examples out there.

It provides for an overwriteExisting flag for choice. Consequently, if the overwriteExisting flag is false, the file will not be moved and the folder containing the file would not be removed.

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

I have spent about 3 hours testing this in many different scenarios, and it works most of the time. Although, sometimes, it gives me an Access denied code(5) error on Windows, which I have been unable to figure out. This is why I have put the clearstatcache() function up at the top, after reading up on its documentation. I don't know whether this is its appropriate usage. I can definitely imagine that it would slow down the function.

I can also imagine that this method may be faster than the copy -> unlink cycle, because if a target sub-folder does not exist, the whole folder tree below would be just moved. However, I am not sure and don't have the experience to conduct exhaustive tests, yet.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Manish
  • 87
  • 7
  • You deserve 10 upvotes, not just one. _thank you_ for sharing this approach. –  Dec 02 '22 at 10:04
0

I use it

// 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 );
    }
}
Bradmage
  • 1,233
  • 1
  • 15
  • 41
Neeraj
  • 8,625
  • 18
  • 60
  • 89