@Felix: Me preguntaba lo mismo. Regresé a la primera revisión, pero lo ha hecho "old_location/*.*. No puedo encontrar una revisión que contenga "old_location/.".
Asaph
@Asaph: Tu retroceso estuvo bien, mira la historia ... quise decircopy ("old_location/.","new_location/");
Felix Kling
3
@dave ¿Cuándo recogerás un :) aceptado?
Nam G VU
Respuestas:
239
Parece que la copia solo maneja archivos únicos . Aquí hay una función para copiar de forma recursiva que encontré en esta nota en la página de documentación de copia :
@ Oliboy50: Puede preguntarle a la persona que escribió el código hace 5 años: php.net/manual/en/function.copy.php#91010 . Tal vez era más popular en aquel entonces suprimir los mensajes de error.
Funcionó muy bien para copiar una carpeta con 140 subcarpetas y cada subcarpeta que contiene 21 imágenes. ¡Funciona genial! ¡Gracias!
Darksaint2014
1
mkdirdebe agregarse truecomo el último parámetro para admitir el directorio recursivo, entonces este script es perfecto
ZenithS
Esto copia la carpeta completa? ¿Qué sucede si solo desea copiar los archivos dentro de la carpeta, sin la carpeta principal, como dice la pregunta: copy ("old_location/*.*","new_location/");¿Funciona eso? ¿Qué pasa si tiene archivos de puntos, serán emparejados?
XCS
35
copy () solo funciona con archivos.
Tanto los comandos de copia de DOS como los de Unix cp se copiarán de forma recursiva, por lo que la solución más rápida es simplemente utilizarlos. p.ej
`cp -r $src $dest`;
De lo contrario, deberá usar el opendir/ readdiro scandirpara leer el contenido del directorio, iterar a través de los resultados y si is_dir devuelve verdadero para cada uno, repita en él.
Aquí hay una versión más estable y limpia de xcopy () que no crea la carpeta si 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
¡Gracias por la solución de backtick ! Una página que me ayudó a ajustar el comando de copia: UNIX cp explicó . Información adicional: PHP> = 5.3 ofrece algunos buenos iteradores
No funcionará en servidores Windows u otros entornos en los que o bien tienen ningún acceso a cualquiera shell_execo cp. Eso hace que, en mi opinión, no sea la "mejor" solución.
The Pellmeister
3
Aparte de eso, los controles de línea de comandos de un archivo PHP pueden ser un gran problema cuando alguien encuentra la manera de obtener un archivo en su servidor.
Martijn
¡Trabajado como un encanto! En CentOS y funcionó muy bien. Gracias @bstpierre
Nick Green
1
Esto no funcionará en Windows en absoluto, porque cpes un comando de Linux. Para uso de Windows xcopy dir1 dir2 /e /i, donde /esignifica copiar /idirectorios vacíos e ignorar preguntas sobre archivos o directorios
Michel
Sí, es la mejor solución si su servidor admite este comando y tiene los permisos necesarios. Es muy rápido. Lamentablemente no funciona en todos los entornos.
Como se dijo en otra parte, copysolo funciona con un solo archivo para la fuente y no con un patrón. Si desea copiar por patrón, use globpara determinar los archivos, luego ejecute la copia. Sin embargo, esto no copiará subdirectorios ni creará el directorio de destino.
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
considere cambiar: $ dest = realpath ($ dir. DIRECTORY_SEPARATOR). nombre base ($ archivo); con: $ dest = realpath ($ dir). DIRECTORIO_SEPARADOR. nombre base ($ archivo);
Agradezco totalmente a Felix Kling por su excelente respuesta que agradecidamente he usado en mi código. Ofrezco una pequeña mejora de un valor de retorno booleano para informar el éxito o el fracaso:
está utilizando recurse_copy () y recurseCopy () como nombres de funciones, actualícelo.
AgelessEssence
El closedir ($ dir); La instrucción debe estar fuera de la instrucción if ($ reslut === true), es decir, una llave más abajo. De lo contrario, corre el riesgo de tener recursos no liberados.
Mi versión podada de @Kzoty responde. Gracias Kzoty
Uso
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();}}
Tuve una situación similar en la que necesitaba copiar de un dominio a otro en el mismo servidor. Esto es exactamente lo que funcionó en mi caso, también puede ajustarlo para adaptarse al suyo:
Observe el uso de "substr ()", sin él, el destino se convierte en '/home/user/abcde.com/../folder/', que podría ser algo que no desea. Entonces, utilicé substr () para eliminar los primeros 3 caracteres (../) para obtener el destino deseado que es '/home/user/abcde.com/folder/'. Por lo tanto, puede ajustar la función substr () y también la función glob () hasta que se ajuste a sus necesidades personales. Espero que esto ayude.
"old_location/."
solo fue un error tipográfico?"old_location/*.*
. No puedo encontrar una revisión que contenga"old_location/."
.copy ("old_location/.","new_location/");
Respuestas:
Parece que la copia solo maneja archivos únicos . Aquí hay una función para copiar de forma recursiva que encontré en esta nota en la página de documentación de copia :
fuente
@mkdir
lugar demkdir
?Como se describe aquí , este es otro enfoque que también se ocupa de los enlaces simbólicos:
fuente
mkdir
debe agregarsetrue
como el último parámetro para admitir el directorio recursivo, entonces este script es perfectocopy ("old_location/*.*","new_location/");
¿Funciona eso? ¿Qué pasa si tiene archivos de puntos, serán emparejados?copy () solo funciona con archivos.
Tanto los comandos de copia de DOS como los de Unix cp se copiarán de forma recursiva, por lo que la solución más rápida es simplemente utilizarlos. p.ej
De lo contrario, deberá usar el
opendir
/readdir
oscandir
para leer el contenido del directorio, iterar a través de los resultados y si is_dir devuelve verdadero para cada uno, repita en él.p.ej
fuente
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 mejor solución es!
fuente
shell_exec
ocp
. Eso hace que, en mi opinión, no sea la "mejor" solución.cp
es un comando de Linux. Para uso de Windowsxcopy dir1 dir2 /e /i
, donde/e
significa copiar/i
directorios vacíos e ignorar preguntas sobre archivos o directoriosfuente
Como se dijo en otra parte,
copy
solo funciona con un solo archivo para la fuente y no con un patrón. Si desea copiar por patrón, useglob
para determinar los archivos, luego ejecute la copia. Sin embargo, esto no copiará subdirectorios ni creará el directorio de destino.fuente
desde la última cuarta línea, haz esto
y
fuente
Agradezco totalmente a Felix Kling por su excelente respuesta que agradecidamente he usado en mi código. Ofrezco una pequeña mejora de un valor de retorno booleano para informar el éxito o el fracaso:
fuente
Con Symfony, esto es muy fácil de lograr:
Ver https://symfony.com/doc/current/components/filesystem.html
fuente
Mi versión podada de @Kzoty responde. Gracias Kzoty
Uso
fuente
Clono todo el directorio mediante el iterador de directorio SPL.
fuente
fuente
Para los servidores Linux solo necesita una línea de código para copiar de forma recursiva mientras conserva el permiso:
Otra forma de hacerlo es:
pero es más lento y no conserva los permisos.
fuente
Tuve una situación similar en la que necesitaba copiar de un dominio a otro en el mismo servidor. Esto es exactamente lo que funcionó en mi caso, también puede ajustarlo para adaptarse al suyo:
Observe el uso de "substr ()", sin él, el destino se convierte en '/home/user/abcde.com/../folder/', que podría ser algo que no desea. Entonces, utilicé substr () para eliminar los primeros 3 caracteres (../) para obtener el destino deseado que es '/home/user/abcde.com/folder/'. Por lo tanto, puede ajustar la función substr () y también la función glob () hasta que se ajuste a sus necesidades personales. Espero que esto ayude.
fuente