Php का उपयोग करके किसी निर्देशिका की संपूर्ण सामग्री को दूसरे में कॉपी करें


146

मैंने निर्देशिका की संपूर्ण सामग्री का उपयोग करके किसी अन्य स्थान पर प्रतिलिपि बनाने का प्रयास किया

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

लेकिन यह कहता है कि यह धारा को सही नहीं पा सकता है *.* नहीं पाया गया है।

कोई अन्य तरीका

धन्यवाद डेव


1
@ संपादकों: क्या आपको यकीन है कि "old_location/."सिर्फ एक टाइपो था?
फेलिक्स क्लिंग

रिच रोडेकर के पास अपने ब्लॉग पर एक स्क्रिप्ट है जो ऐसा करने के लिए प्रकट होती है। दिखाई-form.com/blog/copy-directory-in-php
जॉन एफ हैनकॉक

@ फेलिक्स: मैं एक ही बात सोच रहा था। मैं पहले संशोधन के लिए वापस आ गया लेकिन यह है "old_location/*.*। मुझे कोई संशोधन नहीं मिल रहा है "old_location/."
असफ

@ आसफ: आपका रोलबैक ठीक था, इतिहास पर नजर डालें ... मेरा मतलब थाcopy ("old_location/.","new_location/");
फेलिक्स क्लिंग

3
@ कब स्वीकार करेंगे आप :)?
नाम जी VU

जवाबों:


239

ऐसा लगता है कि प्रतिलिपि केवल एकल फ़ाइलों को संभालती है । यहाँ एक प्रतिलिपि प्रतिलिपि बनाने के लिए एक समारोह है जो मुझे इस नोट में कॉपी प्रलेखन पृष्ठ पर मिला है :

<?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
यह एक तारांकित है और एक तारा नहीं है;)
गॉर्डन

6
आकर्षण की तरह काम करता है .. धन्यवाद @FelixKling
मिलाप

2
@mkdirइसके बजाय क्यों mkdir?
ऑलिबॉय 50

3
@ Oliboy50: आप उस व्यक्ति से पूछ सकते हैं जिसने 5 साल पहले कोड लिखा था: php.net/manual/en/function.copy.php#91010 । हो सकता है कि यह त्रुटि संदेशों को दबाने के लिए अधिक लोकप्रिय था।
फेलिक्स क्लिंग

1
@ ओलिबॉय 50: मैं देख रहा हूं। मुझे लगता है कि यह किसी भी त्रुटि संदेश को दबा देता है। मैं वास्तव में हालांकि यह इस्तेमाल कभी नहीं किया। यह दस्तावेज है: us3.php.net/manual/en/language.operators.errorcontrol.php
फेलिक्स क्लिंग

90

जैसा कि यहां बताया गया है , यह एक और दृष्टिकोण है जो सहानुभूति का भी ख्याल रखता है:

/**
 * 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 उप फ़ोल्डर और 21 छवियों वाले प्रत्येक सबफ़ोल्डर के साथ एक फ़ोल्डर की प्रतिलिपि बनाने के लिए बहुत अच्छा काम किया। बहुत अच्छा काम करता है! धन्यवाद!
Darksaint2014

1
mkdirtrueपुनरावर्ती निर्देशिका का समर्थन करने के लिए अंतिम पैरामीटर के रूप में जोड़ा जाना चाहिए फिर यह स्क्रिप्ट एकदम सही है
जेनिथ्स

यह संपूर्ण फ़ोल्डर की प्रतिलिपि बनाता है? क्या होगा यदि आप केवल फ़ोल्डर के अंदर , मूल फ़ोल्डर के बिना, फ़ाइलों को कॉपी करना चाहते हैं , जैसा कि सवाल कहता है: copy ("old_location/*.*","new_location/");क्या वह काम करता है? यदि आपके पास डॉट फाइलें हैं, तो क्या उनका मिलान किया जाएगा?
XCS

35

कॉपी () केवल फाइलों के साथ काम करता है।

डॉस कॉपी और यूनिक्स cp कमांड दोनों ही रिकर्सिवली कॉपी करेंगे - इसलिए क्विक सॉल्यूशन सिर्फ इनको शेल करना और इनका इस्तेमाल करना है। जैसे

`cp -r $src $dest`;

अन्यथा आपको opendir/ readdirया का उपयोग करने की आवश्यकता होगीscandir निर्देशिका की सामग्री को पढ़ने के , परिणाम के माध्यम से पुनरावृत्ति करना और यदि is_dir प्रत्येक के लिए सही है, तो उसमें पुन: प्रयास करें।

जैसे

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

1
यहाँ xcopy () का एक और अधिक स्थिर और क्लीनर संस्करण है जो मौजूद नहीं होने पर फ़ोल्डर नहीं बनाता है: 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

Backtick समाधान के लिए धन्यवाद ! एक पृष्ठ जिसने मुझे कॉपी कमांड को मोड़ने में मदद की: UNIX cp समझाया गया । अतिरिक्त जानकारी: PHP> = 5.3 कुछ अच्छे
पुनरावृत्तियों की

21

सबसे अच्छा समाधान है!

<?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
?>

31
विंडोज सर्वर या अन्य वातावरण पर काम नहीं करेंगे जहां या तो आपकी पहुंच नहीं है shell_execया cp। यह बनाता है - मेरी राय में - शायद ही "सबसे अच्छा" समाधान।
पल्मीिस्टर

3
इसके अलावा, PHP फ़ाइल से कमांडलाइन नियंत्रण एक बड़ी समस्या हो सकती है जब कोई व्यक्ति आपके सर्वर पर फ़ाइल प्राप्त करने का तरीका ढूंढता है।
Martijn

एक जादू की तरह काम किया! CentOS पर और इसने बहुत अच्छा काम किया। धन्यवाद @bstpierre
निक ग्रीन

1
यह विंडोज पर बिल्कुल काम नहीं करेगा, क्योंकि cpलिनक्स कमांड है। विंडोज के उपयोग के लिए xcopy dir1 dir2 /e /i, जहाँ /eकॉपी खाली डायरियों के लिए और /iफाइलों या निर्देशिकाओं के बारे में सवालों को अनदेखा करने के लिए है
मिशेल

हां, यह सबसे अच्छा समाधान है यदि आपका सर्वर इस कमांड का समर्थन करता है और आपके पास आवश्यक अनुमतियां हैं। यह बहुत तेज़ है। दुर्भाग्य से सभी वातावरण काम नहीं कर रहे हैं।
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 );
    }
}

अच्छी तरह से काम! धन्यवाद भाई
रॉबिन डेलापोर्टे

8

जैसा कि कहीं और कहा गया है, copyकेवल स्रोत के लिए एक फ़ाइल के साथ काम करता है , न कि एक पैटर्न। यदि आप पैटर्न द्वारा कॉपी करना चाहते हैं glob, तो फ़ाइलों को निर्धारित करने के लिए उपयोग करें, फिर कॉपी चलाएं। हालांकि, यह उपनिर्देशिका की नकल नहीं करेगा और न ही यह गंतव्य निर्देशिका बनाएगा।

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

बदलने पर विचार करें: $ dest = realpath ($ dir। DIRECTORY_SEPARATOR)। basename ($ फ़ाइल); साथ: $ भाग्य = realpath ($ dir)। DIRECTORY_SEPARATOR। basename ($ फ़ाइल);
दाऊजी

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

अंतिम 4 पंक्ति से, इसे बनाएं

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

तथा

$destination ='b';

7

पूर्ण धन्यवाद उनके उत्कृष्ट उत्तर के लिए फेलिक्स क्लिंग को जाना चाहिए जो मैंने अपने कोड में कृतज्ञतापूर्वक उपयोग किया है। मैं सफलता या विफलता की रिपोर्ट करने के लिए बूलियन रिटर्न मान की एक छोटी वृद्धि प्रदान करता हूं:

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
आप recurse_copy () और recurseCopy () फ़ंक्शन नामों के रूप में उपयोग कर रहे हैं, इसे अपडेट करें।
AgelessEssence

बंद करने वाला ($ dir); बयान के बाहर होने की जरूरत है ($ reslut === सच) बयान, यानी एक घुंघराले ब्रेस आगे नीचे। अन्यथा आप गैर मुक्त संसाधनों के जोखिम में हैं।
दिमितर दाराज़न्स्की


5

@Kzoty उत्तर का मेरा छंटा हुआ संस्करण। धन्यवाद Kzoty

प्रयोग

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

}

1

मैं SPL निर्देशिका 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");


0

लिनक्स सर्वर के लिए आपको अनुमति को संरक्षित करते हुए पुन: प्रतिलिपि बनाने के लिए कोड की एक पंक्ति की आवश्यकता होती है:

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

इसे करने का दूसरा तरीका है:

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

लेकिन यह धीमा है और अनुमतियों को संरक्षित नहीं करता है।


0

मेरे पास एक समान स्थिति थी जहां मुझे एक ही सर्वर पर एक डोमेन से दूसरे में कॉपी करने की आवश्यकता थी, यहां बिल्कुल वही है जो मेरे मामले में काम करता है, आप अपने अनुरूप करने के लिए समायोजित कर सकते हैं:

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

"रूट ()" के उपयोग पर ध्यान दें, इसके बिना, गंतव्य '/home/user/abcde.com/../folder/' हो जाता है, जो कुछ ऐसा हो सकता है जो आप नहीं चाहते हैं। इसलिए, मैंने वांछित गंतव्य को प्राप्त करने के लिए पहले 3 अक्षर (../) को खत्म करने के लिए () /home/user/abcde.com/folder/ का उपयोग किया। इसलिए, आप रूट () फ़ंक्शन और ग्लोब () फ़ंक्शन को तब तक समायोजित कर सकते हैं जब तक कि यह आपकी व्यक्तिगत आवश्यकताओं के अनुरूप न हो। उम्मीद है की यह मदद करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.