Copiar directorios y subdirectorios de forma recursiva con PHP
Bienvenidos a VerTutoriales.com, en esta ocasión os traigo una función que parece ser que en internet hay mucho tema abierto pero ninguno concluye una función que copie realmente una carpeta exactamente como queremos, es decir, con las subcarpetas (tantas como sean) y todos su archivos, por supuesto.
Así que me puse manos a la obra, y utilizando una función lo que hago es llamar a esta tantas veces como directorios o carpetas anidadas tenga, de esta manera entrará en cada una de ellas, la creará de igual manera en la carpeta destino e irá copiando los archivos que vaya encontrando en su sitio. Vamos a ver la función y luego explico brevemente los parámetros, aunque creo que está bien claro el código.
<?
//Recojo el valor de donde copio y donde tengo que copiar
function copia($dirOrigen, $dirDestino)
{
//Creo el directorio destinomkdir($dirDestino, 0777, true);
//abro el directorio origenif ($vcarga = opendir($dirOrigen))
{
while($file = readdir($vcarga)) //lo recorro enterito
{
if ($file != “.” && $file != “..”) //quito el raiz y el padre
{
echo “<b>$file</b>”; //muestro el nombre del archivo
if (!is_dir($dirOrigen.$file)) //pregunto si no es directorio
{
if(copy($dirOrigen.$file, $dirDestino.$file)) //como no es directorio, copio de origen a destino
{
echo ” COPIADO!”;
}else{
echo ” ERROR!”;
}
}else{
echo ” — directorio — <br />”; //era directorio llamo a la función de nuevo con la nueva ubicación
copia($dirOrigen.$file.”/”, $dirDestino.$file.”/”);
}
echo “<br />”;
}
}
closedir($vcarga);
}
}$destino=”carpetanueva/”;
$origen = “privado/”;copia($origen, $destino)
?>
Bueno pues esta es la función, la llamada está clara que es copia(“directorioOrigen/”, “directorioDestino/”). La función como dije está bien comentada, pero explicando muy brevemente, lo que hacemos es recorrer el directorio actual y vamos copiando los archivos que encontremos en la carpeta destino, cuando en ese listado que recorremos encontramos una carpeta, directamente llamamos a la misma función pero con los parámetros de origen y destino actualizados con la nueva carpeta, y repetimos la operación tantas veces como carpetas tenga, una vez que termina con el directorio, sale de la función y continua por donde iba. Esto lo repetirá tantas veces como sea necesario, en las pruebas no me ha tardado en copiar un número aceptable de carpetas-archivos, así que lo dejo aquí para que lo utilceis en vuestros códigos.
Se aceptan gracias y por supuesto aportes para mejora. Hay que tener en cuenta que el directorio lo creo con todos los permisos, quizás sea necesario tener en cuenta el cambiar luego los permisos o ponerles otros. Eso cada cual.
Venga un saludo.



9 Respuestas
Javier Hernandez
marzo 13th, 2011 a 11:20 pm
1Excelente la rutina, realmente no hay que modificarle nada y adicionarle tampoco, cumple a cabalidad su proposito..
..Gracias por el aporte
VideoTutoriales
marzo 14th, 2011 a 8:49 am
2Gracias, la verdad que no encontré ningún código que lo realizara integramente. Así que tuve que pelearme con ello, lo peor de todo es que ahroa estoy peleandome con los permisos en el servidor y creo que tendré que hacerlo finalmente con las funciones de ftp.
Un saludo!
luisg123v
octubre 7th, 2011 a 12:03 am
3El único problema con ese código es que si por ejemplo un fichero o directorio tiene un nombre que pueda ser evaluado como false (por ejemplo “0″) el ciclo while dejará de iterar.
Para que esto no suceda, habría que hacer algo como esto:
while(false !== ($file = readdir($vcarga)))
De manera de asegurar que el ciclo va a iterar hasta que el valor devuelto por readdir($vcarga) sea exactamente false, y no algo que pueda ser evaluado como false.
Salu2
VideoTutoriales
octubre 7th, 2011 a 7:01 am
4Interesante, me gustaría saber con qué te has encontrado para llegar a tal código
Por cierto, el while tendría que quedar:
while(false != ($file = readdir($vcarga)))
Le sobraba un =
Gracias por el aporte. Un saludo!
luisg123v
octubre 7th, 2011 a 4:50 pm
5Precisamente ese igual de mas es necesario, para obligar a que no solo sea false, si no que sea exactamente del mismo tipo. Es decir, que sea booleano.
Explicación de los operadores:
!=: Distintos resultados, independientemente de los tipos de variables.
!==: Distintos resultados, para variables del mismo tipo.
==: Resultados iguales, independientemente de los tipos de variables.
===: Resultados iguales, del mismo tipo de variable obligatoriamente.
…
Si no estuviera ese = de mas, sería equivalente al ciclo while original, ya que lo que hace el ciclo es exactamente eso, iterar mientras sea distinto de false.
Salu2.
andres
octubre 15th, 2011 a 5:33 pm
6Muy buena .. lo anduve buscando por horas esto y lo encontre gracias a ustedes .
PD : Por si a alguien le sirve revisen bien las comillas estas ( ” ) cuando copian a Dreamweaver porque en realidad son las simples como estas ( ‘ ) . Tambien otra cosa , si alguno quiere definir una variable dentro del destino ponganlo asi :
$destino=”carpeta/$variable/”;
$origen = ‘capeta/’;
si se fijan el origen esta con comillas simples y el destino con dobles . A mi me volvio loco eso pero cambiandole las comillas funciono perfectamente .
MIL GRACIAS A TODOS DESDE ARGENTINA
VideoTutoriales
octubre 17th, 2011 a 9:46 pm
7Gracias a tí Andrés.
Creo que el problema de las comillas, no es por las comillas simples o dobles, son por que en realidad al copiar y pegar toma otros caracteres y no los típicos “”
Espero que ayuden a mucha más gente con dudas
Guillermo
octubre 30th, 2011 a 4:23 am
8Hola!
Excelente código, impecable!!
Solo que me quedo con una duda….
En esta parte…
if ($file != “.” && $file != “..”) //quito el raiz y el padre
A que te refieres con quitar raíz y padre?
Saludos!
VideoTutoriales
octubre 30th, 2011 a 7:43 am
9Todo directorio tiene para el sistema el directorio “.” que es si mismo, por eso cuando se localiza un directorio o vas a dar una url se suele poner “./carpeta/” o “./archivo.ext” si te fijas lleva un punto delante y si nos vamos con “..” es el directorio padre, el ejemplo sería “../carpeta/” o “../archivo.ext” lo cual nos llevaría al directorio que contiene desde el que estamos llamandolo.
El hecho de quitarlos es para que no nos dé error, aparte que carecería de sentido ya que cada directorio los tiene.
Insertar al RSS los comentarios de esta entrada
Escribe tu comentario