Copy all file in folder php

I tried to copy the entire contents of the directory to another location using

copy ["old_location/*.*","new_location/"];

but it says it cannot find stream, true *.* is not found.

Any other way

Thanks Dave

Asaph

155k25 gold badges190 silver badges194 bronze badges

asked Jan 12, 2010 at 17:17

5

that worked for a one level directory. for a folder with multi-level directories I used this:

function recurseCopy[
    string $sourceDirectory,
    string $destinationDirectory,
    string $childFolder = ''
]: void {
    $directory = opendir[$sourceDirectory];

    if [is_dir[$destinationDirectory] === false] {
        mkdir[$destinationDirectory];
    }

    if [$childFolder !== ''] {
        if [is_dir["$destinationDirectory/$childFolder"] === false] {
            mkdir["$destinationDirectory/$childFolder"];
        }

        while [[$file = readdir[$directory]] !== false] {
            if [$file === '.' || $file === '..'] {
                continue;
            }

            if [is_dir["$sourceDirectory/$file"] === true] {
                recurseCopy["$sourceDirectory/$file", "$destinationDirectory/$childFolder/$file"];
            } else {
                copy["$sourceDirectory/$file", "$destinationDirectory/$childFolder/$file"];
            }
        }

        closedir[$directory];

        return;
    }

    while [[$file = readdir[$directory]] !== false] {
        if [$file === '.' || $file === '..'] {
            continue;
        }

        if [is_dir["$sourceDirectory/$file"] === true] {
            recurseCopy["$sourceDirectory/$file", "$destinationDirectory/$file"];
        }
        else {
            copy["$sourceDirectory/$file", "$destinationDirectory/$file"];
        }
    }

    closedir[$directory];
}

Max

3451 gold badge3 silver badges10 bronze badges

answered Jan 12, 2010 at 17:23

Felix KlingFelix Kling

767k171 gold badges1068 silver badges1114 bronze badges

9

As described here, this is another approach that takes care of symlinks too:

/**
 * Copy a file, or recursively copy a folder and its contents
 * @author      Aidan Lister 
 * @version     1.0.1
 * @link        //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]
{
    $sourceHash = hashDirectory[$source];
    // 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
        if[$sourceHash != hashDirectory[$source."/".$entry]]{
             xcopy["$source/$entry", "$dest/$entry", $permissions];
        }
    }

    // Clean up
    $dir->close[];
    return true;
}

// In case of coping a directory inside itself, there is a need to hash check the directory otherwise and infinite loop of coping is generated

function hashDirectory[$directory]{
    if [! is_dir[$directory]]{ return false; }

    $files = array[];
    $dir = dir[$directory];

    while [false !== [$file = $dir->read[]]]{
        if [$file != '.' and $file != '..'] {
            if [is_dir[$directory . '/' . $file]] { $files[] = hashDirectory[$directory . '/' . $file]; }
            else { $files[] = md5_file[$directory . '/' . $file]; }
        }
    }

    $dir->close[];

    return md5[implode['', $files]];
}

answered Oct 6, 2012 at 21:17

itsjaviitsjavi

2,5762 gold badges20 silver badges24 bronze badges

3

copy[] only works with files.

Both the DOS copy and Unix cp commands will copy recursively - so the quickest solution is just to shell out and use these. e.g.

`cp -r $src $dest`;

Otherwise you'll need to use the opendir/readdir or scandir to read the contents of the directory, iterate through the results and if is_dir returns true for each one, recurse into it.

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

answered Jan 12, 2010 at 17:32

symcbeansymcbean

46.9k6 gold badges56 silver badges89 bronze badges

2

The best solution is!


bstpierre

28.9k14 gold badges67 silver badges101 bronze badges

answered Apr 21, 2011 at 0:28

blackblack

3453 silver badges2 bronze badges

7

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

Mr.Wizard

24k5 gold badges42 silver badges119 bronze badges

answered Apr 29, 2011 at 15:47

kzotykzoty

1511 silver badge2 bronze badges

1

Like said elsewhere, copy only works with a single file for source and not a pattern. If you want to copy by pattern, use glob to determine the files, then run copy. This will not copy subdirectories though, nor will it create the destination directory.

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

answered Jan 12, 2010 at 18:10

GordonGordon

307k72 gold badges525 silver badges549 bronze badges

1


from the last 4th line , make this

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

and

$destination ='b';

Guern

1,1891 gold badge11 silver badges30 bronze badges

answered Mar 6, 2013 at 20:40

0

Full thanks must go to Felix Kling for his excellent answer which I have gratefully used in my code. I offer a small enhancement of a boolean return value to report success or failure:

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

answered Jan 4, 2013 at 11:23

gonzogonzo

5186 silver badges6 bronze badges

2

My pruned version of @Kzoty answer. Thank you 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[];
    }

}

answered Dec 10, 2011 at 19:59

Nam G VUNam G VU

31.4k67 gold badges218 silver badges355 bronze badges

I clone entire directory by 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"];

answered Jan 11, 2018 at 12:36

For Linux servers you just need one line of code to copy recursively while preserving permission:

exec['cp -a '.$source.' '.$dest];

Another way of doing it is:

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

but it's slower and does not preserve permissions.

answered Oct 24, 2018 at 19:00

Dan BrayDan Bray

6,7403 gold badges49 silver badges63 bronze badges

I had a similar situation where I needed to copy from one domain to another on the same server, Here is exactly what worked in my case, you can as well adjust to suit yours:

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

Notice the use of "substr[]", without it, the destination becomes '/home/user/abcde.com/../folder/', which might be something you don't want. So, I used substr[] to eliminate the first 3 characters[../] in order to get the desired destination which is '/home/user/abcde.com/folder/'. So, you can adjust the substr[] function and also the glob[] function until it fits your personal needs. Hope this helps.

answered Apr 27, 2020 at 23:52

ChimdiChimdi

1571 silver badge7 bronze badges

Long-winded, commented example with return logging, based on parts of most of the answers here:

It is presented as a static class method, but could work as a simple function also:

/**
 * Recursive copy directories and content
 * 
 * @link        //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 like:

// 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 ] ];

answered Sep 10, 2020 at 8:49

Q StudioQ Studio

1,7763 gold badges15 silver badges17 bronze badges

// using exec

function rCopy[$directory, $destination]
{

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

    exec[$command];

}

answered Jul 11, 2018 at 7:56

For copy entire contents from a directory to another, first you should sure about transfer files that they were transfer correctly. for this reason, we use copy files one by one! in correct directories. we copy a file and check it if true go to next file and continue...

1- I check the safe process of transferring each file with this function:


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- Now i copy files one by one from src into dest, check it and then continue. [For separate the folders that i don't want to copy them, use exclude array]

$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 . '
'; }else{ echo 'Failed transfer for:' . $srcPath . '
'; } } } } }

answered Jun 20, 2021 at 5:46

1

I find this to be way simpler, more easily customizable, and to not require any dependency:

foreach[glob["old_location/*"] as $file] {
    copy[$file, "new_location/" . basename[$file]];
}

answered Aug 18 at 18:19

Vic SeedoubleyewVic Seedoubleyew

9,8916 gold badges50 silver badges71 bronze badges

Not the answer you're looking for? Browse other questions tagged php or ask your own question.

Chủ Đề