1

I want to copy a whole folders/files tree from one location to another, but for a particular depth I want to perform a transliteration of the destination folder from one language to another.

So for /src/depth1/depth2/depth3/depth4/file I want to transliterate all depth3 folders to another language before copying them over to the destination path.

So I found this little, robust recursive function, which should help me in my task, and then I tried to add a depth control feature so that the transliteration replacement takes place only on depth3 folders. But at first, what I did only added to the depth. Then I thought I found the correct place to add the $depth--;, but unfortunately I can't figure out where to subtract from it in order to start over a new branch...

Could someone help figure this out please?

recurse_copy('TOCOPY/', 'TEST/');

function recurse_copy($src,$dst,$depth = 0) { 
    echo $src . ' ' . $depth.'<br>';
    $dir = opendir($src); 
    @mkdir($dst); 
    while(false !== ( $file = readdir($dir)) ) { 
        $depth++;
        if (( $file != '.' ) && ( $file != '..' )) { 
            if ( is_dir($src . '/' . $file) ) { 
                recurse_copy($src . '/' . $file,$dst . '/' . $file, $depth); 
            } else { 
                $depth--;
              //  copy($src . '/' . $file,$dst . '/' . $file); //I commented this line to save time from copying files again and again while I'm experimenting with the depth control...
            } 
        } 
       
    } 
    closedir($dir); 
}
Faye D.
  • 833
  • 1
  • 3
  • 16

2 Answers2

2

Not tested, but if my understanding is right this should work, plus minus 1 depth.

recurse_copy('TOCOPY/', 'TEST/', 3);

function recurse_copy($src, $dst, $depth = 0) { 
    echo $src . ' ' . $depth . '<br>';
    if ($depth <= 0) {
      return;
    }
    $dir = opendir($src); 
    @mkdir($dst); 
    while(false !== ( $file = readdir($dir)) ) { 
        if (( $file != '.' ) && ( $file != '..' )) { 
            if ( is_dir($src . '/' . $file) ) { 
                recurse_copy($src . '/' . $file,$dst . '/' . $file, $depth - 1); 
            } else { 
              //  copy($src . '/' . $file,$dst . '/' . $file); //I commented this line to save time from copying files again and again while I'm experimenting with the depth control...
            } 
        } 
       
    } 
    closedir($dir); 
}

Addition: This version will rename some directories according to their depth.


recurse_copy_special('TOCOPY/', 'TEST/');

function recurse_copy_special($src, $dst, $depth = 0)
{
    echo $src . ' ' . $depth . '<br>';
    $base = basename($dst);
    $dir = dirname($dst);
    
    if ($depth == 1) {
        $dst = $dir . '/' . 'changed1-' . $base;
    }
    if ($depth == 2) {
        $dst = $dir . '/' . 'changed2-' . $base;
    }
    if ($depth == 3) {
        $dst = $dir . '/' . 'changed3-' . $base;
    }
    $dir = opendir($src);
    if (!file_exists($dst)) {
        mkdir($dst);
    }
    while (false !== ($file = readdir($dir))) {
        if (($file != '.') && ($file != '..')) {
            if (is_dir($src . '/' . $file)) {
                recurse_copy_special($src . '/' . $file, $dst . '/' . $file, $depth + 1);
            } else {
                copy($src . '/' . $file, $dst . '/' . $file);
            }
        }

    }
    closedir($dir);
}
IT goldman
  • 14,885
  • 2
  • 14
  • 28
  • Although this seemed impossible to work, it works... It basically calculates everything the opposite way, meaning that depth is reduced as it goes deeper... Ie, with the debugging echo in place, this is an extract of the outcome TOCOPY/ARENA/001743730 1 TOCOPY/ARENA/001743730/MPLE_KIT 0 TOCOPY/ARENA/1B32851 1 TOCOPY/ARENA/1B32851/MAY 0 TOCOPY/ARENA/001611566 1 TOCOPY/ARENA/001611566/MAY_PRA 0 TOCOPY/ARENA/9239565 1 TOCOPY/ARENA/9239565/MAY_PRA 0 TOCOPY/ARENA/925901 1 TOCOPY/ARENA/925901/ROZ 0 with the depth I'm interested in, being depth 0... Couldn't it be calculated the normal way? – Faye D. Sep 04 '22 at 22:18
  • @FayeD. - Please tick it to indicate that it worked for you. – Rohit Gupta Sep 04 '22 at 22:59
  • @RohitGupta you're right, it worked, so it definitely deserves an upvote, but I'm saving the "accepted answer" to either this if it gets edited, or some other answer, if it appears, that would count things the right way, meaning that it'd increase the counter as we go deeper. – Faye D. Sep 04 '22 at 23:35
  • I'm not sure I understand the requirement. If it counts up, how would it know to stop at depth 3? – IT goldman Sep 05 '22 at 07:26
  • @ITgoldman because it doesn't go any deeper. All images follow the same pattern: root////image1,jpg root////image2,jpg root////image1,jpg etc – Faye D. Sep 05 '22 at 13:00
  • So for (depth 1) I want to replace space with underscore, so folder /Gianfranco Ferre/ would become /Gianfranco_Ferre/ and (depth 3) would have its characters transliterated. – Faye D. Sep 05 '22 at 13:03
  • So you want to copy the entire tree, only manipulate destination names of level 1 and 3? – IT goldman Sep 05 '22 at 15:22
  • @ITgoldman yup, exactly! – Faye D. Sep 06 '22 at 22:51
  • Should be easy. Go indeed with an ascending `$depth` parameter (1 at start, and each level +1). And change the variable `$dst` according to `$depth`. For example, `if ($depth == 3) { $dst = my_transliterate($dst); }` – IT goldman Sep 07 '22 at 05:38
  • @ITgoldman for the sake of getting your answer complete, would you like to reflect your suggestions into your code? You're the only one who genuinely cared so much and your answer deserves to be marked as the solution! – Faye D. Sep 07 '22 at 07:56
  • @ITgoldman this worked like a charm. Your answer was gold! Thank you very much! :D – Faye D. Sep 08 '22 at 22:09
2
recurse_copy('TOCOPY/', 'TEST/', 3);

function recurse_copy($source, $destination, $depth = 0) {
    echo "copy $depth from $source to $destination" . PHP_EOL;
    
    if ($depth < 0) {
        return;
    }

    $directory = opendir($source);

    if (!$directory) {
        return;
    }

    @mkdir($destination); 

    while(false !== ($file = readdir($directory))) { 
        if (in_array($file, ['.', '..'])) {
            continue;
        }

        $currentSourcePath = $source . '/' . $file;
        $currentDestinationPath = $destination . '/' . $file;
        
        if (is_dir($currentSourcePath)) {
            recurse_copy($currentSourcePath, $currentDestinationPath, $depth - 1);
            continue;
        }

        copy($currentSourcePath, $currentDestinationPath);
    }

    closedir($directory); 
}
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 09 '22 at 07:33