@Felix: Je me demandais la même chose. Je suis revenu à la première révision mais c'est le cas "old_location/*.*. Je ne trouve pas de révision contenant "old_location/.".
Asaph
@Asaph: Votre retour en arrière était ok, regardez l'historique ... je voulais direcopy ("old_location/.","new_location/");
Felix Kling
3
@dave Quand récupérerez-vous un accepté :)?
Nam G VU
Réponses:
239
Il semble que la copie ne gère que des fichiers uniques . Voici une fonction de copie récursive que j'ai trouvée dans cette note sur la page de documentation de copie :
@ Oliboy50: Vous pouvez demander à la personne qui a écrit le code il y a 5 ans: php.net/manual/en/function.copy.php#91010 . Il était peut-être plus populaire à l'époque de supprimer les messages d'erreur.
Fonctionne très bien pour copier un dossier avec 140 sous-dossiers et chaque sous-dossier contenant 21 images. Fonctionne très bien! Merci!
Darksaint2014
1
mkdirdevrait être ajouté truecomme dernier paramètre pour prendre en charge récursivement le répertoire alors ce script est parfait
ZenithS
Cela copie le dossier entier? Que faire si vous souhaitez uniquement copier les fichiers à l' intérieur du dossier, sans le dossier parent, comme le dit la question: copy ("old_location/*.*","new_location/");cela fonctionne-t-il? Que faire si vous avez des fichiers de points, seront-ils mis en correspondance?
XCS le
35
copy () ne fonctionne qu'avec les fichiers.
La copie DOS et les commandes Unix cp seront copiées de manière récursive - donc la solution la plus rapide est simplement de décortiquer et de les utiliser. par exemple
`cp -r $src $dest`;
Sinon, vous devrez utiliser le opendir/ readdirou scandirpour lire le contenu du répertoire, parcourir les résultats et si is_dir renvoie true pour chacun d'eux, rentrer dedans.
Voici une version plus stable et plus propre de xcopy () qui ne crée pas le dossier s'il existe: 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
Merci pour la solution backtick ! Une page qui m'a aidé à modifier la commande de copie: UNIX cp expliqué . Informations supplémentaires: PHP> = 5.3 propose de jolis itérateurs
Ne fonctionnera pas sur les serveurs Windows ou d'autres environnements où vous n'avez pas accès à l'un shell_execou l' autre cp. Cela en fait - à mon avis - loin d’être la «meilleure» solution.
The Pellmeister
3
En dehors de cela, les contrôles en ligne de commande à partir d'un fichier PHP peuvent être un gros problème lorsque quelqu'un trouve un moyen d'obtenir un fichier sur votre serveur.
Martijn le
A travaillé comme un charme! Sur CentOS et cela a très bien fonctionné. Merci @bstpierre
Nick Green
1
Cela ne fonctionnera pas du tout sous Windows, car il cps'agit d'une commande Linux. Pour Windows xcopy dir1 dir2 /e /i, où /esignifie copier les /irépertoires vides et ignorer les questions sur les fichiers ou les répertoires
Michel
Oui, c'est la meilleure solution si votre serveur prend en charge cette commande et que vous disposez des autorisations requises. C'est très rapide. Malheureusement, ne fonctionne pas dans tous les environnements.
Comme dit ailleurs, copyne fonctionne qu'avec un seul fichier pour la source et non un modèle. Si vous souhaitez copier par modèle, utilisez globpour déterminer les fichiers, puis exécutez la copie. Cependant, cela ne copiera pas les sous-répertoires, ni ne créera le répertoire de destination.
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
pensez à changer: $ dest = realpath ($ dir. DIRECTORY_SEPARATOR). nom de base ($ fichier); avec: $ dest = realpath ($ dir). DIRECTORY_SEPARATOR. nom de base ($ fichier);
Tous mes remerciements vont à Felix Kling pour son excellente réponse que j'ai utilisée avec gratitude dans mon code. Je propose une petite amélioration d'une valeur de retour booléenne pour signaler le succès ou l'échec:
vous utilisez recurse_copy () et recurseCopy () comme noms de fonction, mettez-le à jour.
AgelessEssence
Le Closedir ($ dir); L'instruction doit être en dehors de l'instruction if ($ reslut === true), c'est-à-dire une accolade plus bas. Sinon, vous risquez d'avoir des ressources non libérées.
Helper::copy($sourcePath, $targetPath);classHelper{staticfunction 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();}}
J'ai eu une situation similaire où je devais copier d'un domaine à un autre sur le même serveur, voici exactement ce qui a fonctionné dans mon cas, vous pouvez également ajuster en fonction du vôtre:
Remarquez l'utilisation de "substr ()", sans lui, la destination devient '/home/user/abcde.com/../folder/', ce que vous ne voulez peut-être pas. Donc, j'ai utilisé substr () pour éliminer les 3 premiers caractères (../) afin d'obtenir la destination souhaitée qui est '/home/user/abcde.com/folder/'. Ainsi, vous pouvez ajuster la fonction substr () ainsi que la fonction glob () jusqu'à ce qu'elle corresponde à vos besoins personnels. J'espère que cela t'aides.
"old_location/."
n'était qu'une faute de frappe?"old_location/*.*
. Je ne trouve pas de révision contenant"old_location/."
.copy ("old_location/.","new_location/");
Réponses:
Il semble que la copie ne gère que des fichiers uniques . Voici une fonction de copie récursive que j'ai trouvée dans cette note sur la page de documentation de copie :
la source
@mkdir
au lieu demkdir
?Comme décrit ici , c'est une autre approche qui prend également en charge les liens symboliques:
la source
mkdir
devrait être ajoutétrue
comme dernier paramètre pour prendre en charge récursivement le répertoire alors ce script est parfaitcopy ("old_location/*.*","new_location/");
cela fonctionne-t-il? Que faire si vous avez des fichiers de points, seront-ils mis en correspondance?copy () ne fonctionne qu'avec les fichiers.
La copie DOS et les commandes Unix cp seront copiées de manière récursive - donc la solution la plus rapide est simplement de décortiquer et de les utiliser. par exemple
Sinon, vous devrez utiliser le
opendir
/readdir
ouscandir
pour lire le contenu du répertoire, parcourir les résultats et si is_dir renvoie true pour chacun d'eux, rentrer dedans.par exemple
la source
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); } } } }
La meilleure solution est!
la source
shell_exec
ou l' autrecp
. Cela en fait - à mon avis - loin d’être la «meilleure» solution.cp
s'agit d'une commande Linux. Pour Windowsxcopy dir1 dir2 /e /i
, où/e
signifie copier les/i
répertoires vides et ignorer les questions sur les fichiers ou les répertoiresla source
Comme dit ailleurs,
copy
ne fonctionne qu'avec un seul fichier pour la source et non un modèle. Si vous souhaitez copier par modèle, utilisezglob
pour déterminer les fichiers, puis exécutez la copie. Cependant, cela ne copiera pas les sous-répertoires, ni ne créera le répertoire de destination.la source
à partir de la dernière quatrième ligne, faites ceci
et
la source
Tous mes remerciements vont à Felix Kling pour son excellente réponse que j'ai utilisée avec gratitude dans mon code. Je propose une petite amélioration d'une valeur de retour booléenne pour signaler le succès ou l'échec:
la source
Avec Symfony, c'est très simple à réaliser:
Voir https://symfony.com/doc/current/components/filesystem.html
la source
Ma version élaguée de @Kzoty répond. Merci Kzoty.
Usage
la source
Je clone l'annuaire entier par SPL Directory Iterator.
la source
la source
Pour les serveurs Linux, vous n'avez besoin que d'une seule ligne de code pour copier récursivement tout en préservant les autorisations:
Une autre façon de procéder est:
mais c'est plus lent et ne préserve pas les permissions.
la source
J'ai eu une situation similaire où je devais copier d'un domaine à un autre sur le même serveur, voici exactement ce qui a fonctionné dans mon cas, vous pouvez également ajuster en fonction du vôtre:
Remarquez l'utilisation de "substr ()", sans lui, la destination devient '/home/user/abcde.com/../folder/', ce que vous ne voulez peut-être pas. Donc, j'ai utilisé substr () pour éliminer les 3 premiers caractères (../) afin d'obtenir la destination souhaitée qui est '/home/user/abcde.com/folder/'. Ainsi, vous pouvez ajuster la fonction substr () ainsi que la fonction glob () jusqu'à ce qu'elle corresponde à vos besoins personnels. J'espère que cela t'aides.
la source