PHP如何复制整个文件夹_PHP复制文件夹及所有文件【教程】

2次阅读

最稳方案是用RecursiveDirectoryIterator+RecursiveIteratorIterator手动递归复制:先mkdir($dst,0755,true),再遍历判断isFile()/isDir()分别处理,支持跨平台、中文路径、空目录,不依赖exec。

PHP如何复制整个文件夹_PHP复制文件夹及所有文件【教程】

php复制整个文件夹:用 RecursivecopyIterator 最稳

原生 PHP 没有直接的 copy_dir() 函数,靠 copy() + 递归遍历才能完成。最可靠的方式是组合 RecursiveDirectoryIteratorRecursiveIteratorIterator,手动创建目标路径并逐个复制文件与子目录。

别用网上流传的“一行 exec('cp -r')”方案——它依赖系统命令、不可移植、有安全风险(尤其当路径含用户输入时),且 windows 完全不兼容。

  • 必须先用 mkdir($dst, 0755, true) 创建目标目录(true 表示递归创建父级)
  • 遍历时跳过 ...,否则会无限递归或报错
  • 判断当前项是文件还是目录:用 $item->isFile()$item->isDir(),别用 is_file() 等函数——迭代器对象本身已封装状态,更准确

简单可用的封装函数:copy_directory()

以下函数经实测可跨 windows / linux 使用,支持空子目录、中文路径(需 PHP 文件系统编码一致),不依赖外部命令:

function copy_directory(string $src, string $dst): bool {     if (!is_dir($src)) {         return false;     }     if (!mkdir($dst, 0755, true) && !is_dir($dst)) {         return false;     }      $iterator = new RecursiveIteratorIterator(         new RecursiveDirectoryIterator($src, RecursiveDirectoryIterator::SKIP_DOTS),         RecursiveIteratorIterator::SELF_FIRST     );      foreach ($iterator as $item) {         $relPath = $iterator->getSubPathName();         $dstPath = $dst . DIRECTORY_SEPARATOR . $relPath;          if ($item->isDir()) {             mkdir($dstPath, 0755, true);         } else {             if (!copy($item->getPathname(), $dstPath)) {                 return false;             }         }     }      return true; }

调用示例:copy_directory('/path/to/src', '/path/to/dst');

立即学习PHP免费学习笔记(深入)”;

注意:RecursiveIteratorIterator::SELF_FIRST 确保目录先于其内容被处理,否则 mkdir 可能失败。

遇到 Permission deniedOperation not permitted 怎么办

这类错误通常不是代码问题,而是权限或系统限制:

  • 目标路径所在分区是否为只读(如挂载的 NTFS 分区在 Linux 下默认无写权限)
  • 源目录中是否有符号链接?RecursiveDirectoryIterator 默认不跟随,若需复制链接本身,加标志 RecursiveDirectoryIterator::FOLLOW_SYMLINKS
  • SELinux 或 macOS 的 SIP(System Integrity Protection)可能拦截操作,临时禁用仅用于调试,生产环境应调整策略而非关闭保护
  • Windows 上某些系统文件(如 Thumbs.db 或回收站 $RECYCLE.BIN)无法读取,需在循环中用 try/catch 捕获 RuntimeException 并跳过

大文件夹复制慢?别盲目加 set_time_limit(0)

超时常见,但根本原因常被忽略:

  • PHP 默认单次脚本执行时间 30 秒,复制上万小文件容易超时——此时应优化为分批处理(例如每 100 个文件 usleep(10000) 防卡死),而非直接关超时
  • 频繁调用 copy() 开销大,可改用 file_get_contents() + file_put_contents() 组合,对小文件略快;但大文件会吃光内存,务必加 stream_copy_to_stream() 流式复制
  • 如果只是部署用途,更推荐用 rsync 或 git 钩子代替运行时 PHP 复制——PHP 不是干这个的

真正难的从来不是“怎么写”,而是判断该不该在 PHP 里做这件事。路径权限、符号链接、稀疏文件、ACL 属性……这些细节一旦漏掉,线上就静默失败。

text=ZqhQzanResources