Bir dizinin tüm içeriğini php kullanarak başka bir dizine kopyalayın


149

Dizinin tüm içeriğini kullanarak başka bir konuma kopyalamaya çalıştım

copy ("old_location/*.*","new_location/");

ama akışı bulamadığını söylüyor, doğru *.*bulunamadı.

Başka türlü

Teşekkürler Dave


1
@the editörler: Bunun "old_location/."sadece bir yazım hatası olduğundan emin misiniz ?
Felix Kling

Rich Rodecker'ın blogunda tam da bunu yapıyor gibi görünen bir komut dosyası var. visible-form.com/blog/copy-directory-in-php
Jon F Hancock

@Felix: Ben de aynı şeyi merak ediyordum. İlk revizyona geri döndüm ama oldu "old_location/*.*. İçeren bir revizyon bulamıyorum "old_location/.".
Asaph

@Asaph: Geri dönüşünüz iyiydi, geçmişe bakın ... Kastettiğimcopy ("old_location/.","new_location/");
Felix Kling

3
@dave Ne zaman kabul edileceğini alacaksın :)?
Nam G VU

Yanıtlar:


241

Kopya görünüyor sadece idare tek dosyaları . İşte bulundu yinelemeli kopyalanması için bir işlevdir bu notta üzerinde kopya dokümantasyon sayfasından :

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

2
Bu bir yıldız işareti ve bir yıldız değil;)
Gordon

6
Büyü gibi İşleri .. teşekkürler @FelixKling
Milap

2
Neden @mkdiryerine mkdir?
Oliboy50

3
@ Oliboy50: 5 yıl önce kodu yazan kişiye sorabilirsiniz: php.net/manual/en/function.copy.php#91010 . Belki o zamanlar hata mesajlarını bastırmak daha popülerdi.
Felix Kling

1
@ Oliboy50: Görüyorum. Herhangi bir hata mesajını bastırdığını düşünüyorum. Aslında onu hiç kullanmadım. Bu belgeler geçerli: us3.php.net/manual/en/language.operators.errorcontrol.php
Felix Kling

90

Burada açıklandığı gibi , bu, sembolik bağlantılarla da ilgilenen başka bir yaklaşımdır:

/**
 * Copy a file, or recursively copy a folder and its contents
 * @author      Aidan Lister <aidan@php.net>
 * @version     1.0.1
 * @link        http://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));
}

140 alt klasör ve 21 resim içeren her alt klasör içeren bir klasörü kopyalamak için harika çalıştı. Harika çalışıyor! Teşekkürler!
Darksaint2014

1
mkdirtrueözyinelemeli dizini desteklemek için son parametre olarak eklenmelidir , bu durumda bu komut dosyası mükemmeldir
ZenithS

Bu, tüm klasörü kopyalar mı? Soruya göre, yalnızca klasör içindeki dosyaları ana klasör olmadan kopyalamak istiyorsanız : copy ("old_location/*.*","new_location/");Bu işe yarıyor mu? Ya nokta dosyalarınız varsa, eşleştirilecekler mi?
XCS

36

copy () yalnızca dosyalarla çalışır.

Hem DOS kopyası hem de Unix cp komutları özyinelemeli olarak kopyalayacaktır - bu nedenle en hızlı çözüm, sadece bunları kullanmaktır. Örneğin

`cp -r $src $dest`;

Aksi takdirde, opendir/ readdirveya scandirdizinin içeriğini kullanmanız, sonuçları yinelemeniz ve is_dir her biri için true değerini döndürürse, içinde tekrar etmeniz gerekir.

Örneğin

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

2
Burada, varsa klasörü oluşturmayan daha kararlı ve daha temiz bir xcopy () sürümü var: function xcopy($src, $dest) { foreach (scandir($src) as $file) { $srcfile = rtrim($src, '/') .'/'. $file; $destfile = rtrim($dest, '/') .'/'. $file; if (!is_readable($srcfile)) { continue; } if ($file != '.' && $file != '..') { if (is_dir($srcfile)) { if (!file_exists($destfile)) { mkdir($destfile); } xcopy($srcfile, $destfile); } else { copy($srcfile, $destfile); } } } }
TheStoryCoder

Ters vuruş çözümü için teşekkürler ! Kopyalama komutunu değiştirmeme yardımcı olan bir sayfa: UNIX cp açıkladı . Ek bilgi: PHP> = 5.3 bazı güzel yineleyiciler
maxpower9000

22

En iyi çözüm!

<?php
$src = "/home/www/domain-name.com/source/folders/123456";
$dest = "/home/www/domain-name.com/test/123456";

shell_exec("cp -r $src $dest");

echo "<H3>Copy Paste completed!</H3>"; //output when done
?>

32
Windows sunucularında veya ya shell_execda erişiminizin olmadığı diğer ortamlarda çalışmaz cp. Bu onu - bence - neredeyse "en iyi" çözüm yapar.
Pellmeister

3
Bunun dışında, bir PHP dosyasındaki komut satırı kontrolleri, birisi sunucunuzda bir dosya almanın bir yolunu bulduğunda büyük bir sorun olabilir.
Martijn

Büyü gibi çalıştı! CentOS'ta harika çalıştı. Teşekkürler @bstpierre
Nick Green

1
Bu cpbir Linux komutu olduğu için Windows'ta hiç çalışmaz . Windows kullanımı için xcopy dir1 dir2 /e /i, burada /eboş dizinleri kopyala ve /idosyalar veya dizinler hakkındaki soruları yok saymak için
Michel

Evet, sunucunuz bu komutu destekliyorsa ve gerekli izinlere sahipseniz bu en iyi çözümdür. Çok hızlı. Ne yazık ki tüm ortamlarda çalışmıyor.
mdikici

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

Mükemmel çalışıyor! Teşekkürler kardeşim
Robin Delaporte


8

Başka bir yerde söylendiği gibi, copyyalnızca kaynak için tek bir dosyayla çalışır, bir kalıpla değil. Desene göre kopyalamak istiyorsanız, kullanarak globdosyaları belirleyin ve ardından kopyalamayı çalıştırın. Bu, alt dizinleri kopyalamayacak ve hedef dizini oluşturmayacaktır.

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

değiştirmeyi düşünün: $ dest = gerçek yol ($ dir. DIRECTORY_SEPARATOR). basename ($ dosya); ile: $ hedef = gerçek yol ($ dir). DIRECTORY_SEPARATOR. basename ($ dosya);
dawez

8
<?php
    function copy_directory( $source, $destination ) {
        if ( is_dir( $source ) ) {
        @mkdir( $destination );
        $directory = dir( $source );
        while ( FALSE !== ( $readdirectory = $directory->read() ) ) {
            if ( $readdirectory == '.' || $readdirectory == '..' ) {
                continue;
            }
            $PathDir = $source . '/' . $readdirectory; 
            if ( is_dir( $PathDir ) ) {
                copy_directory( $PathDir, $destination . '/' . $readdirectory );
                continue;
            }
            copy( $PathDir, $destination . '/' . $readdirectory );
        }

        $directory->close();
        }else {
        copy( $source, $destination );
        }
    }
?>

son 4. satırdan bunu yapın

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

ve

$destination ='b';

7

Kodumda minnetle kullandığım mükemmel cevabı için Felix Kling'e tam teşekkürler. Başarı veya başarısızlığı bildirmek için bir boole dönüş değerinde küçük bir iyileştirme öneriyorum:

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

1
işlev adları olarak recurse_copy () ve recurseCopy () kullanıyorsunuz, güncelleyin.
AgelessEssence

Closedir ($ dir); ifadesi if ($ reslut === true) ifadesinin dışında, yani aşağıda bir kaşlı ayraç olmalıdır. Aksi takdirde, serbest olmayan kaynaklara sahip olma riskini alırsınız.
Dimitar Darazhanski

5

@Kzoty cevabının budanmış hali. Teşekkürler Kzoty.

Kullanım

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

}

2

SPL Directory Iterator ile tüm dizini klonladım.

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

0

Aynı sunucuda bir alandan diğerine kopyalamam gereken benzer bir durum yaşadım, İşte benim durumumda tam olarak işe yarayan şey, sizinkine uyacak şekilde de ayarlayabilirsiniz:

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

"Substr ()" kullanılmadığına dikkat edin, hedef "/home/user/abcde.com/../folder/" olur, bu da istemediğiniz bir şey olabilir. Bu yüzden, '/home/user/abcde.com/folder/' olan istenen hedefi elde etmek için ilk 3 karakteri (../) ortadan kaldırmak için substr () kullandım. Böylece, kişisel ihtiyaçlarınıza uyana kadar substr () işlevini ve ayrıca glob () işlevini ayarlayabilirsiniz. Bu yardımcı olur umarım.


0

Buradaki yanıtların çoğunun bazı kısımlarına dayanan, dönüş günlüğü ile uzun soluklu, yorumlanmış örnek:

Statik bir sınıf yöntemi olarak sunulur, ancak basit bir işlev olarak da çalışabilir:

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

}

Şöyle arayın:

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

-1
// using exec

function rCopy($directory, $destination)
{

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

    exec($command);

}

-1

Linux sunucuları için, izni korurken yinelemeli olarak kopyalamak için yalnızca bir satır koda ihtiyacınız vardır:

exec('cp -a '.$source.' '.$dest);

Bunu yapmanın başka bir yolu:

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

ancak daha yavaştır ve izinleri korumaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.