Рекурсивная копия каталога
На моем старом 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?
Ответы
Ответ 1
Попробуйте что-то вроде этого:
$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
Ответ 2
Я изменил код Джозефа (ниже), потому что он не работал у меня. Это то, что работает:
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);
}
}
[EDIT] добавлен тест перед созданием каталога (строка 7)
Ответ 3
Могу ли я предположить, что (при условии, что это Vix Vix), что вы просто выполняете системный вызов cp -r
, и пусть это сделает для вас копию.
Ответ 4
Вот что мы используем в нашей компании:
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);
}
}
Ответ 5
Symfony FileSystem Component предлагает хорошую обработку ошибок, а также рекурсивное удаление и другие полезные материалы. Используя отличный ответ @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 автономно.
Ответ 6
Эта функция копирует папку recursivley очень прочную. Я скопировал его из раздела комментариев в скопировать команду 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);
}
Ответ 7
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;
}
Ответ 8
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());
}
}
Ответ 9
Я думаю, вы должны проверить пользователя (группу) права. Вы должны рассмотреть chmod, например, в зависимости от того, как вы запускаете (su?) PHP. Возможно, вы также захотите изменить конфигурацию php.
Ответ 10
хмм. как это сложно))
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
Ответ 11
Здесь простая рекурсивная функция для копирования целых каталогов
источник: 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);
}
?>
Ответ 12
Почему бы просто не попросить ОС позаботиться об этом?
system("cp -r olddir newdir");
Готово.
Ответ 13
Были некоторые проблемы с функциями, которые я тестировал в потоке, и вот мощная функция, которая охватывает все. Основные характеристики:
-
Не нужно иметь исходные или промежуточные исходные каталоги. Все каталоги до исходного каталога и скопированных каталогов будут обрабатываться.
-
Возможность пропустить каталог или файлы из массива. (необязательно) С 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);
}