Créer le fichier clone-tree.php avec le contenu suivant :

<?php

class TreeCloner
{
    public function cloneTree($src, $dest, $vars)
    {
        if (false === is_dir($dest)) {
            mkdir($dest);
        }
        foreach(scandir($src) as $item) {
            if ('.' === $item || '..' === $item) {
                continue;
            }
            $sPath = $src . '/' . $item;
            $dPath = $dest . '/' 
                . $this->replace($item, $vars);

            if (true === is_dir($sPath)) {
                mkdir($dPath);
                $this->cloneTree($sPath, $dPath, $vars);
            } else {
                $raw = file_get_contents($sPath);
                $generated = $this->replace($raw, $vars);
                file_put_contents($dPath, $generated);
            }
        }
        return $this;
    }
    
    public function replace($txt, $vars)
    {
        $m = null;
        if (0 >= preg_match_all(
        	"|\%\{([^\}]+)\}|",$txt,$m
            )) {
            return $txt;
        }
        
        for($i = 0; $i<count($m[0]);$i++) {
            $key  = $m[1][$i];
            $sPos = strpos($key, ':');
            $func = null;
            if (false !== $sPos) {
                list($func, $key) = explode(':', $key, 2);
            }
            if (null !== $func) {
                if ('php' === trim(strtolower($func))) {
                    $value = eval('return ('. $key . ');');
                } else {
                    if (false === isset($vars[$key])) {
                        continue;
                    }
                    $value = $vars[$key];
                    $value = $func($value);
                }
            } else {
                if (false === isset($vars[$key])) {
                    continue;
                }
                $value = $vars[$key];
            }
            $txt = str_replace($m[0][$i], $value, $txt);
        }
        return $txt;
    }
}

if (4 !== count($_SERVER['argv'])) {
    die("Syntax: php ".basename(__FILE__).
    " <src> <dest> <variables.ini>
"
    );
}

$cloner = new TreeCloner();
$cloner->cloneTree(
    $argv[1], $argv[2], parse_ini_file($argv[3])
);

Vous pouvez maintenant utiliser le cloneur d'arborescence comme suit :

  • créer une arborescence modèle dans un répertoire (appellons le 'source'), vous pouvez utiliser des "variables" comme suit: %{name} sera remplacé par la valeur de la variable name dans le fichier ini. Vous pouvez utiliser %{maVariable} dans le contenu d'un fichier (txt, php, xml, pptx, docx, csv, js, css ...) ou bien même dans le nom d'un fichier ou d'un répertoire !
  • créer un fichier de paramétrage avec les différentes variables et leur valeur (appellons le vars.ini) :
name=Olivier
lastname=Hoareau
email=olivier@phppro.fr
...
  • exécutez la ligne de commande suivante pour générer l'arborescence à partir de votre modèle :
$ php clone-tree.php source destination vars.ini

Vous devriez avoir une belle arborescence finale dans le répertoire destination !

Et vous, comment faites vous pour générer des arborescences complexes pour vos projets ? Zend_Tool et autres Symfony et CakePHP pour les projets de ce type, mais pour les autres types de projets ?

Une variante possible : réaliser un .phar ou bien utiliser la directive / fonction __halt_compiler() (voir http://php.net/manual/fr/function.halt-compiler.php) pour embarquer l'ensemble de l'arborescence (zippée) dans votre fichier php (un peu le principe des .phar), ce qui permettra de ne fournir que le fichier de paramètres et le nom du répertoire de destination !