私の古いVPSでは、次のコードを使用して、ディレクトリ内のファイルとディレクトリを、ユーザーがフォームを送信した後に作成された新しいディレクトリにコピーしていました。
function copyr($source, $dest)
{
// Simple copy for a file
if (is_file($source)) {
return copy($source, $dest);
}
// Make destination directory
if (!is_dir($dest)) {
mkdir($dest);
$company = ($_POST['company']);
}
// Loop through the folder
$dir = dir($source);
while (false !== $entry = $dir->read()) {
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}
// Deep copy directories
if ($dest !== "$source/$entry") {
copyr("$source/$entry", "$dest/$entry");
}
}
// Clean up
$dir->close();
return true;
}
copyr('Template/MemberPages', "Members/$company")
ただし、新しいVPSでは、メインディレクトリが作成されるだけで、ファイルはコピーされません。 2つのVPSの間で何が変更されたのか理解できません。
次のようなものを試してください:
$source = "dir/dir/dir";
$dest= "dest/dir";
mkdir($dest, 0755);
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());
}
}
イテレータはすべてのフォルダとサブフォルダを反復処理し、$source
から$dest
へのファイルのコピーを作成します
(* nix VPSであると仮定して)cp -r
へのシステムコールを実行し、コピーを実行することをお勧めしますか?.
ジョセフのコード(下記)を変更しました。機能しなかったためです。これが機能します:
function cpy($source, $dest){
if(is_dir($source)) {
$dir_handle=opendir($source);
while($file=readdir($dir_handle)){
if($file!="." && $file!=".."){
if(is_dir($source."/".$file)){
if(!is_dir($dest."/".$file)){
mkdir($dest."/".$file);
}
cpy($source."/".$file, $dest."/".$file);
} else {
copy($source."/".$file, $dest."/".$file);
}
}
}
closedir($dir_handle);
} else {
copy($source, $dest);
}
}
[編集]ディレクトリを作成する前にテストを追加(7行目)
SymfonyのFileSystemコンポーネント は、優れたエラー処理と、再帰的な削除やその他の便利な機能を提供します。 @OzzyCzechの素晴らしい答えを使用して、次のように堅牢な再帰コピーを実行できます。
use Symfony\Component\Filesystem\Filesystem;
// ...
$fileSystem = new FileSystem();
if (file_exists($target))
{
$this->fileSystem->remove($target);
}
$this->fileSystem->mkdir($target);
$directoryIterator = new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($directoryIterator, \RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $item)
{
if ($item->isDir())
{
$fileSystem->mkdir($target . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
}
else
{
$fileSystem->copy($item, $target . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
}
}
注:このコンポーネントだけでなく、他のすべてのSymfony2コンポーネントをスタンドアロンで使用できます。
これが私たちの会社で使用するものです:
static public function copyr($source, $dest)
{
// recursive function to copy
// all subdirectories and contents:
if(is_dir($source)) {
$dir_handle=opendir($source);
$sourcefolder = basename($source);
mkdir($dest."/".$sourcefolder);
while($file=readdir($dir_handle)){
if($file!="." && $file!=".."){
if(is_dir($source."/".$file)){
self::copyr($source."/".$file, $dest."/".$sourcefolder);
} else {
copy($source."/".$file, $dest."/".$file);
}
}
}
closedir($dir_handle);
} else {
// can also handle simple copy commands
copy($source, $dest);
}
}
この関数は、フォルダーを再帰的に非常に強固にコピーします。 php.netのコピーコマンド のコメントセクションからコピーしました
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);
}
OzzyCheckはエレガントでオリジナルですが、最初のmkdir($ dest)を忘れていました。下記参照。コピーコマンドがコンテンツのみで提供されることはありません。それはその全体的な役割を果たす必要があります。
$source = "dir/dir/dir";
$dest= "dest/dir";
mkdir($dest, 0755);
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());
}
}
function recurse_copy($source, $dest)
{
// 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);
}
// Loop through the folder
$dir = dir($source);
while (false !== $entry = $dir->read()) {
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}
// Deep copy directories
recurse_copy("$source/$entry", "$dest/$entry");
}
// Clean up
$dir->close();
return true;
}
これは、ディレクトリ全体をコピーする単純な再帰関数です
ソース: http://php.net/manual/de/function.copy.php
<?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);
}
?>
User(group)rightsをチェックすべきだと思います。 chmodは、たとえば実行方法(su?)PHPに応じて検討する必要があります。 php設定を変更することもできます。
<?php
/**
* code by Nk ([email protected])
*/
class filesystem
{
public static function normalizePath($path)
{
return $path.(is_dir($path) && !preg_match('@/$@', $path) ? '/' : '');
}
public static function rscandir($dir, $sort = SCANDIR_SORT_ASCENDING)
{
$results = array();
if(!is_dir($dir))
return $results;
$dir = self::normalizePath($dir);
$objects = scandir($dir, $sort);
foreach($objects as $object)
if($object != '.' && $object != '..')
{
if(is_dir($dir.$object))
$results = array_merge($results, self::rscandir($dir.$object, $sort));
else
array_Push($results, $dir.$object);
}
array_Push($results, $dir);
return $results;
}
public static function rcopy($source, $dest, $destmode = null)
{
$files = self::rscandir($source);
if(empty($files))
return;
if(!file_exists($dest))
mkdir($dest, is_int($destmode) ? $destmode : fileperms($source), true);
$source = self::normalizePath(realpath($source));
$dest = self::normalizePath(realpath($dest));
foreach($files as $file)
{
$file_dest = str_replace($source, $dest, $file);
if(is_dir($file))
{
if(!file_exists($file_dest))
mkdir($file_dest, is_int($destmode) ? $destmode : fileperms($file), true);
}
else
copy($file, $file_dest);
}
}
}
?>
/var/www/websiteA/backup.php:
<?php /* include.. */ filesystem::rcopy('/var/www/websiteA/', '../websiteB'); ?>
OSにこの処理を依頼するだけではどうですか。
system("cp -r olddir newdir");
できました。
うーん。複雑なので))
function mkdir_recursive( $dir ){
$prev = dirname($dir);
if( ! file_exists($prev))
{
mkdir_recursive($prev);
}
if( ! file_exists($dir))
{
mkdir($dir);
}
}
...
foreach( $files as $file){
mkdir_recursive( dirname( $dir_d . $file));
copy( $dir_s . $file, $dir_d . $file);
}
$file
-そのようなものwww/folder/ahah/file.txt
スレッドでテストした関数にいくつかの問題があり、すべてをカバーする強力な関数があります。ハイライト:
最初または中間のソースディレクトリを用意する必要はありません。ソースディレクトリおよびコピーされたディレクトリまでのすべてのディレクトリが処理されます。
アレイからディレクトリまたはファイルをスキップする機能。 (オプション)
global $skip;
サブレベルのディレクトリの下でもファイルのスキップが処理されます。完全な再帰サポート、複数の深さのすべてのファイルとディレクトリがサポートされています。
$from = "/path/to/source_dir";
$to = "/path/to/destination_dir";
$skip = array('some_file.php', 'somedir');
copy_r($from, $to, $skip);
function copy_r($from, $to, $skip=false) {
global $skip;
$dir = opendir($from);
if (!file_exists($to)) {mkdir ($to, 0775, true);}
while (false !== ($file = readdir($dir))) {
if ($file == '.' OR $file == '..' OR in_array($file, $skip)) {continue;}
if (is_dir($from . DIRECTORY_SEPARATOR . $file)) {
copy_r($from . DIRECTORY_SEPARATOR . $file, $to . DIRECTORY_SEPARATOR . $file);
}
else {
copy($from . DIRECTORY_SEPARATOR . $file, $to . DIRECTORY_SEPARATOR . $file);
}
}
closedir($dir);
}