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 destino

mkdir($dirDestino, 0777, true);
//abro el directorio origen

if ($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.

Te puede interesar:

31 comentarios

  • Javier Hernandez commented on 13 marzo, 2011 Reply

    Excelente la rutina, realmente no hay que modificarle nada y adicionarle tampoco, cumple a cabalidad su proposito..

    ..Gracias por el aporte

    • VideoTutoriales commented on 14 marzo, 2011 Reply

      Gracias, 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 commented on 7 octubre, 2011 Reply

    El ú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 commented on 7 octubre, 2011 Reply

      Interesante, 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 commented on 7 octubre, 2011 Reply

    Precisamente 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 commented on 15 octubre, 2011 Reply

    Muy 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 commented on 17 octubre, 2011 Reply

      Gracias 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 commented on 30 octubre, 2011 Reply

    Hola!

    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 commented on 30 octubre, 2011 Reply

      Todo 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.

  • March commented on 2 mayo, 2013 Reply

    Gracias

  • March commented on 2 mayo, 2013 Reply

    Disculpa, y si el directorio de origen ya existe??

    • VideoTutoriales commented on 4 mayo, 2013 Reply

      Si el directorio existe, no lo crea 🙂

      Creo recordar que sobreescribe la información que encuentre, pero prueba antes 🙂 y si puedes comentas la experiencia.

      Un saludo!

  • Luis commented on 28 junio, 2013 Reply

    Cómo podemos modificar este codigo que funciona bien, para poder copiar carpetas de un FTP a una carpeta local ?

  • robert commented on 14 octubre, 2013 Reply

    ese codigo cuando lo copias y pegas te da un error, al principio pensaba que las llaves d’ator estaban mal cerradas pero tras comprobar que estan bien no veo el fallo

    no funciona :&

    • VideoTutoriales commented on 14 octubre, 2013 Reply

      ¿Qué error te da? El código está en producción y como tal funcionando sin problemas, comprueba que tengas permisos de usuario en el FTP

  • Natalia commented on 7 noviembre, 2013 Reply

    Muy buen código, una duda, como puedo hacer que este código me copie los archivos de una carpeta de un FTP a una carpeta local??

    • VideoTutoriales commented on 14 noviembre, 2013 Reply

      Para ello necesitas utilizar una función de FTP como bien dices, este código utiliza solo funciones de servidor.

      Un saludo!

  • POLLITO3 commented on 29 marzo, 2014 Reply

    Hola no logro hacerlo funcionar con un formulario que cree una carpeta como destino

    • videotutoriales commented on 31 marzo, 2014 Reply

      Si quieres crear carpetas o copiar ficheros y demás, tendrás que tener permisos para ello, revisa que el usuario que estás utilizando para el script de tu PHP tenga permisos de escritura.

      Un saludo!

  • Alfonso commented on 14 abril, 2014 Reply

    No me funciona favor su ayuda
    <?

    //Recojo el valor de donde copio y donde tengo que copiar
    function copia($dirOrigen, $dirDestino)
    {
    //Creo el directorio destino

    mkdir($dirDestino, 0777, true);
    //abro el directorio origen

    if ($vcarga = opendir($dirOrigen))
    {
    while($file = readdir($vcarga)) //lo recorro enterito
    {
    if ($file != "." && $file != "..") //quito el raiz y el padre
    {
    echo "$file“;
    //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 — “;
    //era directorio llamo a la función de nuevo con la nueva ubicación
    copia($dirOrigen.$file.”/”, $dirDestino.$file.”/”);
    }
    echo “”;
    }
    }
    closedir($vcarga);
    }

    }

    $destino=”carpetaD/”;
    $origen = “carpetaO/”;

    copia($origen, $destino)

    ?>

    • videotutoriales commented on 14 abril, 2014 Reply

      Buenas, comprueba que tengas permisos de escritura, el código como comentaba, está en producción por lo que funciona sin problema.

      Posiblemente sea problema de los permisos y para el usuario de PHP para la copia de ficheros te diga que no puede.

      ¿Qué error te devuelve?

      Un saludo!

  • Gerardo commented on 11 junio, 2014 Reply

    Buenisimo es justo lo que andaba buscando para un proyecto que estoy haciendo, gracias

    • videotutoriales commented on 11 junio, 2014 Reply

      Me alegro que te sirva el código en php para copiar directorios de forma recursiva jeje

      Gracias por comentar!
      Un saludo!

  • Maximiliano commented on 26 agosto, 2014 Reply

    Muchas gracias!, andaba necesitando asi para un desarrollo que estoy haciendo actualmente.

    Saludos!

    • videotutoriales commented on 27 agosto, 2014 Reply

      Me alegro que te ayude el código PHP para copiar de forma recursiva ficheros y directorios!

      Un saludo!

  • lidershinobi commented on 12 diciembre, 2014 Reply

    es mucho perdir pero tengo un problema mi objetivo es crear id de cuentas de logins lo que necesito es tomar 2 variables de la base de datos el id y el nombre pero quiero crear una carpeta con un php y crearlo en el directorio que yo quiero

    mi codigo lo que hace es crea una carpeta despues se crea el archivo php con su nombre de una variable despues crea su contenido dentro y finaliza cerrando el archivo lo siguente es renombra la carpeta con la otra variable
    pero todo eso se crea donde tengo el php y intento buscar un codigo entendible donde lea la variable de la carpeta y me lo mueva junto con su archivo php o lo que tiene la carpeta ala otra carpeta de sessions
    bueno almenos quiero saber como mover la carpeta con sus archivos a otro directorio

    • videotutoriales commented on 12 diciembre, 2014 Reply

      Buenas Lider Shinobi 😉

      Si quieres mover contenido puedes utilizar la shell de tu sistema, entiendo que si estás utilizando PHP estás sobre un sistema Linux, por lo que puedes utilizar la propia Shell que trae PHP para lidiar con comandos de Linux o sino la propia función copy($archivo, $nuevo_archivo) de PHP.

      No sé en el punto que te encuentras, si has conseguido crear la carpeta, crear el fichero PHP escribiendo como si fuera un fichero de texto, pero guardando con extensión PHP, etc…

      De todas maneras si desglosas el desarrollo podría serte más concreto 😉
      Sea como sea, suerte con la programación!

  • gabriel ramirez commented on 29 septiembre, 2015 Reply

    buenas tardes me gustaria saber como configurar para que en la variable destino ponga una carpeta alojada en un servidor web , gracias y saludos

    • gabriel ramirez commented on 29 septiembre, 2015 Reply

      Lo que ise fue colocar el archivo php en el servidor pero al momento de correrlo desde el servidor , crea la carpeta destino , pero de la carpeta origen no me copia nada a la carpeta destino

      carpeta origen = carpeta local
      carpeta destino = carpeta remota

      saludos y gracias

      • Carlos Dk commented on 6 octubre, 2015 Reply

        Si te crea la carpeta es por que no existe, sino lo que puede ocurrir es que esas rutas sigan incorrectas.

    • Carlos Dk commented on 6 octubre, 2015 Reply

      Tal y como se hace la llamada $origen = “privado/”; privado/ es la carpeta origen a copiar $destino también puedes indicar el destino en el que copiar, o desde donde copiarlo 😉

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *