As far as recursive copy, something like this seems to work fine for me:
<?php
$output = shell_exec( " cp -r -a dir_source/* dir_dest 2>&1 " )
echo $output
?>
Of course you need to get all your permissions clear. You can do the necessary stuff to use variables.
You could also do this to create the destination directory:
<?php
shell_exec( " cp -r -a dir_source dir_dest 2>&1 " )
?>
This will create a new directory called "dir_dest" if it does not already exist. This is a bit risky though if your situation is ambiguous, and you want to continue to make backups etc, 'cause if you do it twice you end up with:
dir_destination/dir_source
to avoid that one could do something like:
<?php
shell_exec( " mkdir dir_dest; cp -r -a dir_source/* dir_dest 2>&1 " )
?>
Maybe someone can tell me when or why it would be better to use all that PHP code I see here.
copy
(PHP 4, PHP 5)
copy — Copies file
Description
bool copy
( string $source
, string $dest
[, resource $context
] )
Makes a copy of the file source to dest .
If you wish to move a file, use the rename() function.
Parameters
- source
-
Path to the source file.
- dest
-
The destination path. If dest is a URL, the copy operation may fail if the wrapper does not support overwriting of existing files.
WarningIf the destination file already exists, it will be overwritten.
- context
-
A valid context resource created with stream_context_create().
Return Values
Returns TRUE on success or FALSE on failure.
Changelog
| Version | Description |
|---|---|
| 5.3.0 | Added context support. |
| 4.3.0 | Both source and dest may now be URLs if the "fopen wrappers" have been enabled. See fopen() for more details. |
Examples
Example #1 copy() example
<?php
$file = 'example.txt';
$newfile = 'example.txt.bak';
if (!copy($file, $newfile)) {
echo "failed to copy $file...\n";
}
?>
copy
allasso residing at signalmesa dot com
28-Nov-2008 11:15
28-Nov-2008 11:15
marajax at gmail dot com
01-Nov-2008 04:14
01-Nov-2008 04:14
Hi, I made few changes to make it usable also on Linux servers (useful if your development is on Linux and production server is Windows).
<?php
function dir_copy($srcdir, $dstdir, $offset = '', $verbose = false)
{
// A function to copy files from one directory to another one, including subdirectories and
// nonexisting or newer files. Function returns number of files copied.
// This function is PHP implementation of Windows xcopy A:\dir1\* B:\dir2 /D /E /F /H /R /Y
// Syntaxis: [$returnstring =] dircopy($sourcedirectory, $destinationdirectory [, $offset] [, $verbose]);
// Example: $num = dircopy('A:\dir1', 'B:\dir2', 1);
// Original by SkyEye. Remake by AngelKiha.
// Linux compatibility by marajax.
// Offset count added for the possibilty that it somehow miscounts your files. This is NOT required.
// Remake returns an explodable string with comma differentiables, in the order of:
// Number copied files, Number of files which failed to copy, Total size (in bytes) of the copied files,
// and the files which fail to copy. Example: 5,2,150000,\SOMEPATH\SOMEFILE.EXT|\SOMEPATH\SOMEOTHERFILE.EXT
// If you feel adventurous, or have an error reporting system that can log the failed copy files, they can be
// exploded using the | differentiable, after exploding the result string.
//
if(!isset($offset)) $offset=0;
$num = 0;
$fail = 0;
$sizetotal = 0;
$fifail = '';
if(!is_dir($dstdir)) mkdir($dstdir);
if($curdir = opendir($srcdir)) {
while($file = readdir($curdir)) {
if($file != '.' && $file != '..') {
// $srcfile = $srcdir . '\\' . $file; # deleted by marajax
// $dstfile = $dstdir . '\\' . $file; # deleted by marajax
$srcfile = $srcdir . '/' . $file; # added by marajax
$dstfile = $dstdir . '/' . $file; # added by marajax
if(is_file($srcfile)) {
if(is_file($dstfile)) $ow = filemtime($srcfile) - filemtime($dstfile); else $ow = 1;
if($ow > 0) {
if($verbose) echo "Copying '$srcfile' to '$dstfile'...<br />";
if(copy($srcfile, $dstfile)) {
touch($dstfile, filemtime($srcfile)); $num++;
chmod($dstfile, 0777); # added by marajax
$sizetotal = ($sizetotal + filesize($dstfile));
if($verbose) echo "OK\n";
}
else {
echo "Error: File '$srcfile' could not be copied!<br />\n";
$fail++;
$fifail = $fifail.$srcfile.'|';
}
}
}
else if(is_dir($srcfile)) {
$res = explode(',',$ret);
$ret = dircopy($srcfile, $dstfile, $verbose);
$mod = explode(',',$ret);
$imp = array($res[0] + $mod[0],$mod[1] + $res[1],$mod[2] + $res[2],$mod[3].$res[3]);
$ret = implode(',',$imp);
}
}
}
closedir($curdir);
}
$red = explode(',',$ret);
$ret = ($num + $red[0]).','.(($fail-$offset) + $red[1]).','.($sizetotal + $red[2]).','.$fifail.$red[3];
return $ret;
}
?>
AngelKiha
10-Oct-2008 07:16
10-Oct-2008 07:16
Thanks SkyEye for a wonderful copy program that I can work with. Being a info-lover, I've changed your datacopy() a bit. I've added more information than just the number of files copied. It now shows Number of files, number of failed files, total amount of data copied (in bytes, i think), and the path to the failed files. It could probably be cleaned up a little, but I'm too lazy to do so, as it is very efficient right now.
<?php
// A function to copy files from one directory to another one, including subdirectories and
// nonexisting or newer files. Function returns number of files copied.
// This function is PHP implementation of Windows xcopy A:\dir1\* B:\dir2 /D /E /F /H /R /Y
// Syntaxis: [$returnstring =] dircopy($sourcedirectory, $destinationdirectory [, $offset] [, $verbose]);
// Example: $num = dircopy('A:\dir1', 'B:\dir2', 1);
// Origional by SkyEye. Remake by AngelKiha.
// Offset count added for the possibilty that it somehow miscounts your files. This is NOT required.
// Remake returns an explodable string with comma differentiables, in the order of:
// Number copied files, Number of files which failed to copy, Total size (in bytes) of the copied files,
// and the files which fail to copy. Example: 5,2,150000,\SOMEPATH\SOMEFILE.EXT|\SOMEPATH\SOMEOTHERFILE.EXT
// If you feel adventurous, or have an error reporting system that can log the failed copy files, they can be
// exploded using the | differentiable, after exploding the result string.
function dircopy($srcdir, $dstdir, $offset, $verbose = false) {
if(!isset($offset)) $offset=0;
$num = 0;
$fail = 0;
$sizetotal = 0;
$fifail = '';
if(!is_dir($dstdir)) mkdir($dstdir);
if($curdir = opendir($srcdir)) {
while($file = readdir($curdir)) {
if($file != '.' && $file != '..') {
$srcfile = $srcdir . '\\' . $file;
$dstfile = $dstdir . '\\' . $file;
if(is_file($srcfile)) {
if(is_file($dstfile)) $ow = filemtime($srcfile) - filemtime($dstfile); else $ow = 1;
if($ow > 0) {
if($verbose) echo "Copying '$srcfile' to '$dstfile'...";
if(copy($srcfile, $dstfile)) {
touch($dstfile, filemtime($srcfile)); $num++;
$sizetotal = ($sizetotal + filesize($dstfile));
if($verbose) echo "OK\n";
}
else {
echo "Error: File '$srcfile' could not be copied!\n";
$fail++;
$fifail = $fifail.$srcfile."|";
}
}
}
else if(is_dir($srcfile)) {
$res = explode(",",$ret);
$ret = dircopy($srcfile, $dstfile, $verbose);
$mod = explode(",",$ret);
$imp = array($res[0] + $mod[0],$mod[1] + $res[1],$mod[2] + $res[2],$mod[3].$res[3]);
$ret = implode(",",$imp);
}
}
}
closedir($curdir);
}
$red = explode(",",$ret);
$ret = ($num + $red[0]).",".(($fail-$offset) + $red[1]).",".($sizetotal + $red[2]).",".$fifail.$red[3];
return $ret;
}
?>
xmediasoftware at hotmail dot com
02-Oct-2008 05:59
02-Oct-2008 05:59
<?php
// here is my own version of UploadFile and renameIfExists
// sample: UploadPicture($_FILES['picture'],"images/",true);
// if the third parameter it is true, UploadPicture overwrites the picture
// if it is false, returns the new name and dont overwrites. regards
/////////////////////////
function IfExistsRename($file_name, $new_location){
if(substr($new_location,-1,1) != "/"){
$new_location += $new_location . "/";
}
if(file_exists($new_location . $file_name)){
$cont = 0;
$original_fila_name = $file_name;
do{
$file_parts = explode(".",$original_fila_name,2);
$file_name = $file_parts[0] . $cont . "." . $file_parts[1];
$cont++;
}while(file_exists($new_location . $file_name));
}
return $file_name;
}
function UploadPicture($posted_picture, $new_location, $overwrite){
$file_name ="";
if(substr($new_location,-1,1) != "/"){
$new_location += $new_location . "/";
}
if(!$overwrite){
$file_name = IfExistsRename($posted_picture['name'], $new_location);
}else{
$file_name = $posted_picture['name'];
}
// checking if it was send it by post
if(is_uploaded_file($posted_picture['tmp_name'])){
// Uploading the file with the new name
if(!copy($posted_picture['tmp_name'], $new_location . $file_name)){
echo "Unable to copy the file " . $posted_picture['tmp_name'] . " to the server";
}else{
echo "<!-- Field Copied-->";
}
}else{
echo "Unable to detect the file source";
}
return $file_name;
}
?>
roll dot dev at gmail dot com
04-Sep-2008 05:45
04-Sep-2008 05:45
The windows file system is'nt case sensitive so MyFile.txt and Myfile.txt are the same names.
jim dot mcgowen at cox dot net
14-Jul-2008 05:50
14-Jul-2008 05:50
On Windows (not sure about Linux) copy will overwrite an existing file but will not change the case of the existing filename.
In other words if I have a file named "Myfile.txt" and I overwrite it using copy with a file named "MyFile.txt" it will overwrite it but the filename will remain "Myfile.txt".
If this is a problem (as it was for me) use unlink to delete the existing file first.
steve a h
20-Jun-2008 09:44
20-Jun-2008 09:44
Don't forget; you can use copy on remote files, rather than doing messy fopen stuff. e.g.
<?php
if(!@copy('http://someserver.com/somefile.zip','./somefile.zip'))
{
$errors= error_get_last();
echo "COPY ERROR: ".$errors['type'];
echo "<br />\n".$errors['message'];
} else {
echo "File copied from remote!";
}
?>
tom at r dot je
18-Jun-2008 03:30
18-Jun-2008 03:30
It's worth noting that copy() sets the destination file's last modified time/date.
zeusakm at gmail dot com
06-Jun-2008 08:50
06-Jun-2008 08:50
<?php
//file_upload.php
$archive_dir = "/Inetpub/wwwroot/beginning_php5/ch07/docs";
function upload_form() {
global $PHP_SELF;
?>
<form method="POST" enctype="multipart/form-data" action="<? echo $PHP_SELF ?>">
<input type="hidden" name="action" value="upload">
Upload file!
<input type="file" name="userfile">
<input type="submit" name="submit" value="upload">
</form>
<?php
}
function upload_file() {
global $userfile, $userfile_name, $userfile_size,
$userfile_type, $archive_dir, $WINDIR;
if(isset($WINDIR)) $userfile = str_replace("\\\\","\\", $userfile);
$filename = basename($userfile_name);
if($userfile_size <= 0) die ("$filename is empty.");
if(!@copy($userfile, "$archive_dir/$filename"))
die("Can't copy $userfile_name to $filename.");
if(isset($WINDIR) && !@unlink($userfile))
die ("Can't delete the file $userfile_name.");
echo "$filename has been successfully uploaded.<br>";
echo "Filesize: " . number_format($userfile_size) . "<br>";
echo "Filetype: $userfile_type<br/>";
}
?>
<html>
<head><title>file upload</title></head>
<body>
<?php
if($action == 'upload')
{
upload_file();
} else {
upload_form();
}
?>
</body>
</html>
jyotsnachannagiri at gmail dot com
28-May-2008 03:22
28-May-2008 03:22
I modified the functions posted by mzheng at [s-p-a-m dot ]procuri dot com. Might somebody is looking for to upload only files which have been modified for the last two days like that...
<?php
function dircopy($src_dir, $dst_dir,$UploadDate=false, $verbose = false, $use_cached_dir_trees = false)
{
static $cached_src_dir;
static $src_tree;
static $dst_tree;
$num = 0;
if(($slash = substr($src_dir, -1)) == "\\" || $slash == "/") $src_dir = substr($src_dir, 0, strlen($src_dir) - 1);
if(($slash = substr($dst_dir, -1)) == "\\" || $slash == "/") $dst_dir = substr($dst_dir, 0, strlen($dst_dir) - 1);
if (!$use_cached_dir_trees || !isset($src_tree) || $cached_src_dir != $src_dir)
{
$src_tree = get_dir_tree($src_dir,true,$UploadDate);
$cached_src_dir = $src_dir;
$src_changed = true;
}
if (!$use_cached_dir_trees || !isset($dst_tree) || $src_changed)
$dst_tree = get_dir_tree($dst_dir,true,$UploadDate);
if (!is_dir($dst_dir)) mkdir($dst_dir, 0777, true);
foreach ($src_tree as $file => $src_mtime)
{
if (!isset($dst_tree[$file]) && $src_mtime === false)
mkdir("$dst_dir/$file");
elseif (!isset($dst_tree[$file]) && $src_mtime || isset($dst_tree[$file]) && $src_mtime > $dst_tree[$file])
{
if (copy("$src_dir/$file", "$dst_dir/$file"))
{
if($verbose) echo "Copied '$src_dir/$file' to '$dst_dir/$file'<br>\r\n";
touch("$dst_dir/$file", $src_mtime);
$num++;
} else
echo "<font color='red'>File '$src_dir/$file' could not be copied!</font><br>\r\n";
}
}
return $num;
}
function get_dir_tree($dir, $root = true,$UploadDate)
{
static $tree;
static $base_dir_length;
if ($root)
{
$tree = array();
$base_dir_length = strlen($dir) + 1;
}
if (is_file($dir))
{
if($UploadDate!=false)
{
if(filemtime($dir)>strtotime($UploadDate))
$tree[substr($dir, $base_dir_length)] = date('Y-m-d H:i:s',filemtime($dir));
}
else
$tree[substr($dir, $base_dir_length)] = date('Y-m-d H:i:s',filemtime($dir));
}
elseif ((is_dir($dir) && substr($dir, -4) != ".svn") && $di = dir($dir) )
{
if (!$root) $tree[substr($dir, $base_dir_length)] = false;
while (($file = $di->read()) !== false)
if ($file != "." && $file != "..")
get_dir_tree("$dir/$file", false,$UploadDate);
$di->close();
}
if ($root)
return $tree;
}
$UploadDate = '2008-05-23 13:34:46';
dircopy("/var/www/test", "/var/www/live",$UploadDate);
?>
mzheng at [s-p-a-m dot ]procuri dot com
15-Oct-2007 12:53
15-Oct-2007 12:53
[Updated] A more efficient dircopy function that provides webfarm sync support. :)
<?php
/* Copies a dir to another. Optionally caching the dir/file structure, used to synchronize similar destination dir (web farm).
*
* @param $src_dir str Source directory to copy.
* @param $dst_dir str Destination directory to copy to.
* @param $verbose bool Show or hide file copied messages
* @param $use_cached_dir_trees bool Set to true to cache src/dst dir/file structure. Used to sync to web farms
* (avoids loading the same dir tree in web farms; making sync much faster).
* @return Number of files copied/updated.
* @example
* To copy a dir:
* dircopy("c:\max\pics", "d:\backups\max\pics");
*
* To sync to web farms (webfarm 2 to 4 must have same dir/file structure (run once with cache off to make sure if necessary)):
* dircopy("//webfarm1/wwwroot", "//webfarm2/wwwroot", false, true);
* dircopy("//webfarm1/wwwroot", "//webfarm3/wwwroot", false, true);
* dircopy("//webfarm1/wwwroot", "//webfarm4/wwwroot", false, true);
*/
function dircopy($src_dir, $dst_dir, $verbose = false, $use_cached_dir_trees = false)
{
static $cached_src_dir;
static $src_tree;
static $dst_tree;
$num = 0;
if (($slash = substr($src_dir, -1)) == "\\" || $slash == "/") $src_dir = substr($src_dir, 0, strlen($src_dir) - 1);
if (($slash = substr($dst_dir, -1)) == "\\" || $slash == "/") $dst_dir = substr($dst_dir, 0, strlen($dst_dir) - 1);
if (!$use_cached_dir_trees || !isset($src_tree) || $cached_src_dir != $src_dir)
{
$src_tree = get_dir_tree($src_dir);
$cached_src_dir = $src_dir;
$src_changed = true;
}
if (!$use_cached_dir_trees || !isset($dst_tree) || $src_changed)
$dst_tree = get_dir_tree($dst_dir);
if (!is_dir($dst_dir)) mkdir($dst_dir, 0777, true);
foreach ($src_tree as $file => $src_mtime)
{
if (!isset($dst_tree[$file]) && $src_mtime === false) // dir
mkdir("$dst_dir/$file");
elseif (!isset($dst_tree[$file]) && $src_mtime || isset($dst_tree[$file]) && $src_mtime > $dst_tree[$file]) // file
{
if (copy("$src_dir/$file", "$dst_dir/$file"))
{
if($verbose) echo "Copied '$src_dir/$file' to '$dst_dir/$file'<br>\r\n";
touch("$dst_dir/$file", $src_mtime);
$num++;
} else
echo "<font color='red'>File '$src_dir/$file' could not be copied!</font><br>\r\n";
}
}
return $num;
}
/* Creates a directory / file tree of a given root directory
*
* @param $dir str Directory or file without ending slash
* @param $root bool Must be set to true on initial call to create new tree.
* @return Directory & file in an associative array with file modified time as value.
*/
function get_dir_tree($dir, $root = true)
{
static $tree;
static $base_dir_length;
if ($root)
{
$tree = array();
$base_dir_length = strlen($dir) + 1;
}
if (is_file($dir))
{
//if (substr($dir, -8) != "/CVS/Tag" && substr($dir, -9) != "/CVS/Root" && substr($dir, -12) != "/CVS/Entries")
$tree[substr($dir, $base_dir_length)] = filemtime($dir);
} elseif (is_dir($dir) && $di = dir($dir)) // add after is_dir condition to ignore CVS folders: && substr($dir, -4) != "/CVS"
{
if (!$root) $tree[substr($dir, $base_dir_length)] = false;
while (($file = $di->read()) !== false)
if ($file != "." && $file != "..")
get_dir_tree("$dir/$file", false);
$di->close();
}
if ($root)
return $tree;
}
?>
swizec at swizec dot com
21-Aug-2007 10:54
21-Aug-2007 10:54
Here's another recursive copy function. Unlike the others this one relies on the built-in dir class and is thus much cleaner and simpler.
<?php
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 );
}
}
?>
Flo (somekindofitem.com)
13-Jul-2007 10:05
13-Jul-2007 10:05
here is a a function to move a file clean and safe:
function file_move ($quelle, $ziel)
{
// kopiert datei und loescht sie danach
$fertigverschoben = 4;
if (file_exists($quelle))
{
$fertigverschoben--;
if (!file_exists($ziel))
{
$fertigverschoben--;
if (copy ($quelle, $ziel))
{
$fertigverschoben--;
if (unlink ($quelle)) $fertigverschoben--;
else unlink ($ziel);
}
}
}
return $fertigverschoben;
// gibt errorcode zurueck,
// 0 = alles okay,
// 1 = konnte quelle nicht loeschen,
// 2 = konnte ziel nicht erstellen (copy),
// 3 = ziel existiert bereits,
// 4 = quelle nicht gefunden
}// ende file_move
jtaylor -at- ashevillenc -dot- com
13-Feb-2007 08:48
13-Feb-2007 08:48
It seems as though you can only use move_uploaded_file() once on a temporary file that has been uploaded through a form. Most likely the action this function takes destroys the temporary file after it has been moved, assuming permanent placement on a file system.
Attempting to use the function again in the same PHP script will return false and not move the file.
I ran into this when an image that was uploaded did not need resizing (smaller than a size threshold) and after moving the temporary upload to the "originals" directory, an attempt was made to again move the temporary file to another folder.
This behavior is understandable, but be careful - in this instance, I simply used copy() on the file that was already uploaded.
mspreij
27-Jan-2007 04:35
27-Jan-2007 04:35
hello editor, could you please fix my previous post..
# preg hereunder matches anything with at least one period in the middle (that is,
# non-period characters on either side), and an extension of 1-5 characters
changes to
# preg hereunder matches anything with at least one period in the middle and an extension of 1-5 characters
Sorry!
mspreij
27-Jan-2007 04:20
27-Jan-2007 04:20
This function creates a new filename to use for a copy of the given filename, its behaviour was mostly sto^Wborrowed from how the OS X Finder (*1) does it.
Note it *doesn't* actually copy the file, it just returns the new name. I needed it to work regardless of data source (filesystem, ftp, etc).
It also tries to match the current name as neatly as possible:
foo.txt -> foo copy.txt -> foo copy 1.txt -> foo copy 2.txt [etc]
foo.bar.baz.jpg -> foo.bar.baz copy.jpg
foobar -> foobar copy -> foobar copy 1 [etc]
".txt" -> .txt copy, and "txt." -> txt. copy
file.longextension -> file.longextension copy
It keeps trying until it finds a name that is not yet taken in $list, or until it looped 500 times (change as needed).
If the renamed file becomes longer than max filename length, it starts chopping away at the end of the part before where it adds " copy": reallylong...filename.txt -> reallylong...filena copy.txt
<?php
// $orig = current name, of course
// $list = array of filenames in the target directory (if none given, it will still return a new name)
// $max = max length of filename
function duplicate_name($orig, $list = array(), $max = 64) {
$ext = '';
$counter = 0;
$list = (array) $list;
$max = (int) $max;
$newname = $orig;
do {
$name = $newname; # name in, newname out
if (preg_match('/ copy$| copy \d+$/', $name, $matches)) {
// don't even check for extension, name ends with " copy[ digits]"
// preg hereunder matches anything with at least one period in the middle (that is,
// non-period characters on either side), and an extension of 1-5 characters
}elseif (preg_match('/(.+)\.([^.]{1,5})$/', $name, $parts)) {
// split to name & extension
list($name, $ext) = array($parts[1], $parts[2]);
}
if (preg_match('/ copy (\d+)$/', $name, $digits)) {
$newname = substr($name, 0, - strlen($digits[1])) . ($digits[1] + 1);
# $cutlen is only used for the bit at the end where it checks on max filename length
$cutlen = 6 + strlen($digits[1]+1); // ' copy ' + digits
}elseif(preg_match('/ copy$/', $name, $digits)) {
$newname = $name . ' 1';
$cutlen = 7; // ' copy' + ' 1'
}else{
$newname = $name . ' copy';
$cutlen = 5; // ' copy'
}
if ($ext) {
$newname .= '.' . $ext;
$cutlen += strlen($ext) + 1;
}
if ($max > 0) {
if (strlen($newname) > $max) {
$newname = substr($newname, 0, max($max - $cutlen, 0)) . substr($newname, -$cutlen);
if (strlen($newname) > $max) {echo "duplicate_name() error: Can't keep the new name under given max length.\n"; return false;}
}
}
if ($counter++ > 500) {echo "duplicate_name() error: Too many similarly named files or infinite while loop.\n"; return false;}
} while (in_array($newname, $list));
return $newname;
}
?>
*1) The Finder seems to check the extension vs a list of known extensions, this function considers it valid if it's 5 or fewer characters long.
ps. sorry for taking up so much space! :-)
Belandi
13-Dec-2006 01:09
13-Dec-2006 01:09
To use the previous function on UNIX systems you should change these lines:
$srcfile = $srcdir . '\\' . $file;
$dstfile = $dstdir . '\\' . $file;
To match the following:
$srcfile = $srcdir . DIRECTORY_SEPARATOR . $file;
$dstfile = $dstdir . DIRECTORY_SEPARATOR . $file;
SkyEye
08-Oct-2006 02:21
08-Oct-2006 02:21
<?php
// A function to copy files from one directory to another one, including subdirectories and
// nonexisting or newer files. Function returns number of files copied.
// This function is PHP implementation of Windows xcopy A:\dir1\* B:\dir2 /D /E /F /H /R /Y
// Syntaxis: [$number =] dircopy($sourcedirectory, $destinationdirectory [, $verbose]);
// Example: $num = dircopy('A:\dir1', 'B:\dir2', 1);
function dircopy($srcdir, $dstdir, $verbose = false) {
$num = 0;
if(!is_dir($dstdir)) mkdir($dstdir);
if($curdir = opendir($srcdir)) {
while($file = readdir($curdir)) {
if($file != '.' && $file != '..') {
$srcfile = $srcdir . '\\' . $file;
$dstfile = $dstdir . '\\' . $file;
if(is_file($srcfile)) {
if(is_file($dstfile)) $ow = filemtime($srcfile) - filemtime($dstfile); else $ow = 1;
if($ow > 0) {
if($verbose) echo "Copying '$srcfile' to '$dstfile'...";
if(copy($srcfile, $dstfile)) {
touch($dstfile, filemtime($srcfile)); $num++;
if($verbose) echo "OK\n";
}
else echo "Error: File '$srcfile' could not be copied!\n";
}
}
else if(is_dir($srcfile)) {
$num += dircopy($srcfile, $dstfile, $verbose);
}
}
}
closedir($curdir);
}
return $num;
}
?>
fred dot haab at gmail dot com
19-Aug-2006 12:49
19-Aug-2006 12:49
Just some caveats for people to consider when working with this copy function. Like everyone else, I needed a recursive copy function, so I wrote one.
It worked great until I hit a file greater than 2GB, at which point I got a File Size Exceeded error. I've read that you can recompile PHP with larger file support, but I'm not able to do this on my system.
So I used exec to copy one file at a time (I need to do other things to the file, so can't just do an exec with "cp -r"). Then I ran into problems with spaces in the names. The escapeshellcmd and escapeshellargs functions don't seem to cleanup spaces, so I wrote my own function to do that.
denis at i39 dot ru
10-Aug-2006 12:53
10-Aug-2006 12:53
You can also try to copy with:
<?
exec("cp -r /var/www/mysite /var/backup");
?>
SBoisvert at Don'tSpamMe dot Bryxal dot ca
25-Jul-2006 08:38
25-Jul-2006 08:38
to the editor's: Please pardon me.... remove my other 2 messages and this little comment and just stick this.
just a quick note to add to the great function by:bobbfwed at comcast dot net
this little version has the path not in a define but as a function parameter and also creates the destination directory if it is not already created.
<?php
// copy a directory and all subdirectories and files (recursive)
// void dircpy( str 'source directory', str 'destination directory' [, bool 'overwrite existing files'] )
function dircpy($basePath, $source, $dest, $overwrite = false){
if(!is_dir($basePath . $dest)) //Lets just make sure our new folder is already created. Alright so its not efficient to check each time... bite me
mkdir($basePath . $dest);
if($handle = opendir($basePath . $source)){ // if the folder exploration is sucsessful, continue
while(false !== ($file = readdir($handle))){ // as long as storing the next file to $file is successful, continue
if($file != '.' && $file != '..'){
$path = $source . '/' . $file;
if(is_file($basePath . $path)){
if(!is_file($basePath . $dest . '/' . $file) || $overwrite)
if(!@copy($basePath . $path, $basePath . $dest . '/' . $file)){
echo '<font color="red">File ('.$path.') could not be copied, likely a permissions problem.</font>';
}
} elseif(is_dir($basePath . $path)){
if(!is_dir($basePath . $dest . '/' . $file))
mkdir($basePath . $dest . '/' . $file); // make subdirectory before subdirectory is copied
dircpy($basePath, $path, $dest . '/' . $file, $overwrite); //recurse!
}
}
}
closedir($handle);
}
}
?>
emielm at hotmail dot com
08-Jul-2006 07:49
08-Jul-2006 07:49
I have been puzzling for hours with the copy() function. I got a "no such file or directory" error message all the time (for the source file). In the end my mistake was that there were some spaces at the end of de source filename...
So, if you get file not found errors and you are sure that the file does exists, use the trim() function to get rid of the spaces.
cooper at asu dot ntu-kpi dot kiev dot ua
10-Mar-2006 12:32
10-Mar-2006 12:32
It take me a long time to find out what the problem is when i've got an error on copy(). It DOESN'T create any directories. It only copies to existing path. So create directories before. Hope i'll help,
bobbfwed at comcast dot net
02-Feb-2006 07:06
02-Feb-2006 07:06
I have programmed a really nice program that remotely lets you manage files as if you have direct access to them (http://sourceforge.net/projects/filemanage/). I have a bunch of really handy functions to do just about anything to files or directories.
I know there are others like it, but here is the function I made for this program to copy directories; it will likely need tweaking to work as a standalone script, since it relies of variables set by my program (eg: loc1 -- which dynamically changes in my program):
<?PHP
// loc1 is the path on the computer to the base directory that may be moved
define('loc1', 'C:/Program Files/Apache Group/Apache/htdocs', true);
// copy a directory and all subdirectories and files (recursive)
// void dircpy( str 'source directory', str 'destination directory' [, bool 'overwrite existing files'] )
function dircpy($source, $dest, $overwrite = false){
if($handle = opendir(loc1 . $source)){ // if the folder exploration is sucsessful, continue
while(false !== ($file = readdir($handle))){ 