站群部署完了还在手动建wp-content/uploads?FTP批量创建目录这四种方法,Python脚本最快、WinSCP最稳、lftp最省资源
你刚把第12个WordPress站点部署完,插件上传好了,数据库也导入了,一切就绪。然后你打开FileZilla,连上第一台服务器,右键新建文件夹,输入"wp-content",点确定。再右键,新建"uploads",点确定。再右键,新建"2025",点确定。再右键,新建"07",点确定……三台服务器、十二个站,光建目录就花了四十多分钟。而且建到第八个站的时候手一抖,把"uploads"打成了"upload",第二天才发现图片路径全炸了。
FTP批量创建目录这件事,说大不大说小不小。平时偶尔建几个文件夹不觉得什么,但站点数量一多、服务器一多,它就是消耗运维时间最隐蔽的无底洞。而且手动操作有个致命问题:目录结构只要稍微复杂一点——比如WordPress的上传目录按月分、缓存目录按哈希分、主题子目录按功能分——人工建十次错三次。下面这四种方法,从几分钟搞定到一行命令完事,按你的服务器数量和目录复杂度选就行。
FTP批量创建目录 四种方法速览
| 1 | Python ftplib脚本 —— 适合多服务器+多层级目录,十几行代码跑完所有站点 |
| 2 | WinSCP命令行脚本 —— Windows环境首选,配置文件式管理,改参数不用改代码 |
| 3 | lftp命令行 —— Linux服务器上最轻量,一行命令递归建目录,不占内存 |
| 4 | 宝塔面板 + API批量调用 —— 如果你用宝塔管多台服务器,API一键创建所有站点的FTP目录结构 |
一、Python ftplib脚本,十几行代码跑完所有站点
这是四种方法里最灵活的方案。写一次脚本,之后加站点、改目录结构都只需要改配置文件里的几行文字。Python自带的ftplib库不需要额外安装,Windows和Linux上都能直接跑。
核心逻辑很简单:定义一个目录列表,遍历每个FTP服务器,用mkd()方法逐级创建目录。关键点在于ftplib的mkd()不支持递归——你传"a/b/c"进去它会报错,必须拆成a、b、c三级逐级创建。下面这个脚本已经处理好了这个递归逻辑,可以直接拿去用。
import ftplib# 多台服务器的配置列表SERVERS = [{"host": "192.168.1.10", "user": "ftpuser1", "passwd": "pass1"},{"host": "192.168.1.11", "user": "ftpuser2", "passwd": "pass2"},{"host": "192.168.1.12", "user": "ftpuser3", "passwd": "pass3"},]# 需要创建的目录列表(支持多级路径)DIRS = ["wp-content/uploads/2025","wp-content/uploads/2025/01","wp-content/cache","wp-content/themes/mytheme/assets/css","wp-content/themes/mytheme/assets/js","wp-content/plugins",]def create_remote_dirs(ftp, dir_path):"""递归创建远程目录,自动处理多级路径"""parts = dir_path.strip("/").split("/")current = ""for part in parts:current += "/" + parttry:ftp.cwd(current)except:ftp.mkd(current)print(f" 已创建: {current}")for server in SERVERS:print(f"连接 {server['host']} ...")ftp = ftplib.FTP()ftp.connect(server["host"], 21, timeout=10)ftp.login(server["user"], server["passwd"])for d in DIRS:create_remote_dirs(ftp, d)ftp.quit()print(f"{server['host']} 完成")print("全部服务器目录创建完成")这个脚本的几个设计细节:
· cwd() 先尝试进入目录,如果报错说明不存在,再用 mkd() 创建 —— 这种方式比直接创建更安全,避免重复创建报错
· 用 timeout=10 防止某个服务器连不上卡住整个流程
· SERVERS和DIRS两个列表独立维护,加站点只改服务器列表,加目录只改目录列表,互不影响
如果你管理的站点超过10个,强烈建议把服务器配置和目录列表放到单独的JSON文件里,脚本只负责读取和连接。这样运营同事加新站的时候改JSON就行,不用碰Python代码。

二、WinSCP命令行脚本,Windows环境里最稳的选择
如果你主力用的是Windows,不太想折腾Python环境,WinSCP的命令行模式是个非常稳的替代方案。WinSCP自带一个winscp.com命令行工具,支持写脚本文件批量执行FTP/SFTP操作。而且它有个Python脚本没有的好处:断线重连机制和传输队列管理是内置的,不用自己写异常处理。
用WinSCP做批量建目录,分两步走:先写一个脚本文件(.txt),再写一个bat批处理文件调用它。脚本文件里用mkdir命令一行一个目录,WinSCP会自动处理多级路径。
第一步:创建脚本文件 create_dirs.txt
# WinSCP 批量创建目录脚本# 连接后逐行执行 mkdir 命令option batch onoption confirm offopen ftp://ftpuser1:pass1@192.168.1.10mkdir wp-content/uploads/2025mkdir wp-content/uploads/2025/01mkdir wp-content/uploads/2025/02mkdir wp-content/cachemkdir wp-content/themes/mytheme/assets/cssmkdir wp-content/themes/mytheme/assets/jsmkdir wp-content/pluginscloseexit第二步:创建批处理文件 run.bat
@echo off"C:\Program Files (x86)\WinSCP\winscp.com" /script=create_dirs.txt /log=ftp_log.txtecho 目录创建完成,详细日志见 ftp_log.txtpauseWinSCP方案的局限: 一个脚本文件只能操作一台服务器。如果你有10台服务器,要么写10个脚本文件,要么用一个bat文件循环调用10次winscp.com,每次传不同的参数。服务器数量少于5台的话这个方案最省心,超过5台还是用Python方案更合适。
三、lftp命令行,Linux环境里一行命令搞定
如果你的操作机本身就是Linux服务器,那lftp是资源消耗最小、执行速度最快的方案。它比Python脚本少一层解释器开销,比WinSCP少一个GUI框架依赖,纯C写的,内存占用几乎可以忽略。
lftp最实用的特性是支持从文件读取命令列表,配合shell的循环就能轻松覆盖多台服务器。
# 第一步:创建目录命令文件 dirs_cmd.txt# 每行一个 mkdir 命令,lftp会自动递归创建mkdir -p wp-content/uploads/2025/01mkdir -p wp-content/uploads/2025/02mkdir -p wp-content/cachemkdir -p wp-content/themes/mytheme/assets/cssmkdir -p wp-content/themes/mytheme/assets/jsmkdir -p wp-content/plugins# 第二步:用shell循环对多台服务器执行# servers.txt 每行一个 IPwhile read ip; doecho "处理 $ip ..."lftp -u ftpuser,ftppass -e "source dirs_cmd.txt; quit" ftp://$ipdone < servers.txtlftp 优势
· mkdir -p 原生支持递归创建,不需要自己拆路径
· 支持断点续传和镜像同步(mirror命令),不只是建目录
· 启动速度极快,适合定时任务crontab调用
lftp 注意点
· Windows上需要WSL或Cygwin环境
· 密码写命令行会有安全风险,生产环境建议用 ~/.netrc 文件存认证信息
· FTP over TLS (FTPS) 需要额外指定 set ftp:ssl-force true
四、宝塔面板 + API批量调用,一套面板管N台服务器的目录结构
如果你用宝塔面板管理服务器,FTP批量建目录有一个更省事的路径:直接调用宝塔API,不需要单独连FTP。宝塔面板的API开放了文件管理接口,可以在面板层面直接创建目录,绕过FTP协议层,速度和可靠性都更好。
而且宝塔API返回的是JSON格式的状态码,创建成功、目录已存在、权限不足、路径非法,每种情况都有明确的状态返回。比FTP协议的返回码(比如550错误可能对应十几种不同原因)清晰得多。

import requestsimport json# 宝塔面板的API密钥(面板设置 -> API接口 中获取)BT_KEY = "your_bt_api_key_here"# 多台服务器的面板地址PANELS = [{"url": "https://panel1.example.com:8888", "site_name": "site1.com"},{"url": "https://panel2.example.com:8888", "site_name": "site2.com"},]# 需要创建的目录列表DIRS = ["wp-content/uploads/2025/01","wp-content/uploads/2025/02","wp-content/cache","wp-content/themes/mytheme/assets","wp-content/plugins",]def bt_create_dir(panel_url, site_name, dir_path):"""调用宝塔API创建目录"""api_url = f"{panel_url}/files?action=CreateDir"data = {"path": f"/www/wwwroot/{site_name}/{dir_path}",}# 宝塔API需要签名,这里简化示例,实际需要加上request_token和request_timeheaders = {"User-Agent": "BT-API-Client"}r = requests.post(api_url, data=data, timeout=15)return r.json()for panel in PANELS:print(f"处理 {panel['site_name']} ...")for d in DIRS:result = bt_create_dir(panel["url"], panel["site_name"], d)if result.get("status"):print(f" {d} -> 创建成功")else:print(f" {d} -> {result.get('msg', '未知错误')}")宝塔API方案的优势: 不需要每台服务器单独开FTP端口,面板一个HTTPS端口全搞定。而且API可以同时操作面板上所有站点的文件系统,不需要知道每个站点的FTP账号密码。对于那些FTP账号密码分给不同运营同事、不方便统一收集的情况,这个方案特别实用。
五、四种方法怎么选?一张表看清楚
| 方案 | 最适合的场景 | 上手难度 | 多服务器 | 多级目录 | 运行环境 | 免费 |
|---|---|---|---|---|---|---|
| Python ftplib | 10台以上服务器,目录结构复杂 | 中等 | 强 | 强 | Win/Linux/Mac | 是 |
| WinSCP脚本 | Windows环境,1-5台服务器 | 低 | 一般 | 强 | Windows | 是 |
| lftp | Linux服务器,追求极简和速度 | 低 | 强 | 强 | Linux/WSL | 是 |
| 宝塔API | 已用宝塔面板管多台服务器 | 中等 | 强 | 强 | 任意(通过HTTP) | 是 |
六、批量建目录最容易踩的四个坑,折腾半小时不如先看一遍
坑一:FTP被动模式端口没开
很多服务器只开了21端口,FTP被动模式还需要开放一段高端口范围(通常是30000-50000)。脚本连上后创建目录时报"无法建立数据连接",十有八九是这个问题。Python脚本里加一句 ftp.set_pasv(True) 还不够,服务器防火墙也得放行对应的端口范围。
坑二:目录权限继承不对
FTP创建的目录权限由服务器端的umask决定,不是由脚本决定。脚本建完/wp-content/uploads/后发现网站上传图片报"权限不足",查半天才发现新目录是755而Web进程需要775。要么在脚本里加 ftp.sendcmd("SITE CHMOD 775 xxx"),要么在服务器端调umask。
坑三:中文目录名编码问题
FTP协议默认用ASCII编码,目录名里有中文会导致乱码。Python ftplib默认也是latin-1编码。解决方法:连接后加一行 ftp.encoding = 'utf-8',或者在连接参数里指定。WinSCP默认就是UTF-8,不会遇到这个问题。
坑四:连接超时没做容错
批量跑十几台服务器,中间一台网络抖动或服务挂了,脚本直接抛异常退出,后面的服务器都没处理。解决方案:把每次连接的代码包在 try/except 里,失败了跳过当前服务器继续下一个,最后统一输出失败列表。不要因为一台服务器卡住整个流程。
七、站点多了之后,建目录只是运维自动化的第一环
FTP批量建目录这件事单独拎出来看,解决方案很明确:Python脚本、WinSCP、lftp、宝塔API四选一,十分钟配好就能用。但如果你的站点数量在持续增长——从5个变成15个,再变成30个——建目录只是运维链路上的一小段。前面还有建站、配SSL、装插件、导数据库,后面还有监控索引、检查收录、看排名。每一环都靠手写脚本,到最后你会发现自己变成了半个运维工程师。
这种场景下,把建站和运维流程系统化比单独优化某一个环节更有价值。比如用UC建站系统做多站点部署,站点创建的时候目录结构自动生成、SSL自动申请、FTP权限自动配置,不需要每台服务器单独跑一遍脚本。而且所有站点的索引量、收录率、异常页面在一个统一看板上就能看到,哪个站出了问题第一时间知道,不用一个个登录面板查。
站点数量一多,手工运维的时间成本是指数级增长的
3个站时:建目录5分钟、配SSL 10分钟、装插件 15分钟,总共半小时
10个站时:同样的操作至少3小时,中间还容易出错返工
30个站时:手工根本做不完,任何一个小改动都牵一发动全身
UC建站系统的WP底层+AI管理层架构,把建站、配SSL、FTP目录、插件安装、收录监控这些重复性操作全部自动化。你只需要决定"这批站做什么内容、用什么模板",剩下的目录结构、权限配置、SSL证书、推送通道都由系统自动完成。每个站点独立IP、独立备案、独立模板部署,建完就能开始做内容,不用在运维细节上反复折腾。
说穿了,FTP批量建目录这件事,脚本怎么写是次要的,重要的是先想清楚你的站点规模在哪个阶段。5个站以内,WinSCP脚本跑一次就够;5到20个站,Python脚本+配置文件是最优解;20个站以上,单独解决建目录问题已经没太大意义了,该考虑的是整个部署流程的自动化。
最后给一个实操建议:不管你用哪种方案,建完目录后跑一遍验证脚本,确认所有目录都建对了、权限都设对了。不要建完就认为万事大吉——FTP协议本身就是个"尽力而为"的老协议,它不像HTTP那样有完善的状态码和错误处理。花两分钟验证,比第二天发现图片上传全部报错再去排查要划算得多。
