你大概率遇到过这个需求:给 20 个客户创建统一的资料目录,给 30 个项目初始化一套仓库结构,或者每天按日期生成一组固定的归档文件夹。手动一个一个新建,不仅慢,而且很容易漏掉某一级子目录。更稳的做法是先定义一套“模板结构”,再拿名单批量展开。
这次要解决的问题就是“按模板批量创建文件夹并保留结构”。核心思路是:把目录结构写进一份模板文件,脚本读取模板后,按名单逐项创建,最终每个目录都长成同一套标准结构。
这个方案有四个特点:
- 模板和脚本分离,改结构不用改代码;
- 支持一次传入几十上百个名称,批量生成;
- 创建过程中完整保留多级目录层级,不会把嵌套结构压平;
- 不需要重型依赖,Python 3 标准库即可运行,也提供 Windows 批处理和 PowerShell 版本。
本文会从环境准备讲起,给出 Python 核心脚本,再做现有模板目录复制、Windows 批处理、PowerShell 批量创建和高级自动化扩展。最后补充功能验证、问题排查和工程化建议。
适合已经有命令行基础、需要管理批量目录、或者想把项目脚手架自动化的读者。可以直接收藏,后面用的时候照着复制。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目类型 | 本地脚本工具,无 GUI 依赖 |
| 核心功能 | 按模板批量创建文件夹,完整保留目录结构 |
| 模板定义方式 | JSON 嵌套结构 / 文本路径清单 / 现有模板目录 |
| 运行环境 | Windows、macOS、Linux 均可 |
| 依赖要求 | Python 3.8+,标准库即可,无第三方库 |
| 批量能力 | 支持从 names.txt 读取数量不定的文件夹名称 |
| 接口能力 | 命令行接口为主,可封装为 HTTP 服务 |
| 是否支持覆盖 | 默认不覆盖,重复执行安全 |
| 适合场景 | 项目脚手架、数据归档、客户目录、备份结构初始化 |
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 适用场景与使用边界
2.1 典型场景
批量创建文件夹并不只是一件“懒人工具”,它解决的是结构标准化问题。
- 项目初始化:一批新项目需要统一包含
docs、src、config、scripts目录; - 数据归档:每天或每周生成日期目录,内部再分
raw、processed、output; - 客户资料管理:给多个客户建立独立目录,每个目录内部结构一致;
- 文档仓库初始化:为多个栏目批量生成
images、notes、assets子目录。
这类任务的特征是:名称批量变化,但内部结构固定。如果靠人工逐个操作,很容易出现某个目录多建一层、某个目录少建一层,最后还得统一校验。
2.2 使用边界与合规提醒
这个工具不适合处理需要高度自定义结构的场景。如果每个目录结构都不同,模板化的意义不大,不如直接用交互式文件管理器。
使用边界方面,有几点必须注意:
- 创建目录前先确认目标路径,不要在系统盘根目录或系统关键目录下乱跑脚本;
- 批量命名需要符合公司命名规范,不要直接使用带敏感信息的客户名、手机号、身份证号等字段做公开目录名;
- 如果目录涉及版权素材、用户隐私或商业数据,命名和访问权限都要按合规要求处理;
- 不要用脚本去覆盖他人已有的目录和文件,默认策略应该是“已存在即跳过”。
3. 模板规划与前置准备
3.1 模板要解决的问题
模板是整个批量创建流程的核心。它定义的是“一套标准目录树”,脚本拿到名字后,按模板逐级创建。模板这样做有三个好处:
- 结构可读:打开模板文件,就能看出最终目录长什么样;
- 结构可修改:加一个目录、删一个目录,只改模板,不改脚本;
- 结构可复用:同一套模板可以用在不同批次的名单上。
如果你要把模板放到版本管理里,建议把模板文件和脚本放在同一个仓库目录下,方便追踪变更。
3.2 前置条件清单
| 检查项 | 说明 |
|---|---|
| 操作系统 | Windows / macOS / Linux 均可 |
| Python 版本 | 推荐 3.8 及以上,标准库够用 |
| names.txt 文件 | 每行一个文件夹名称,支持中文 |
| 输出目录 | 指定一个根目录,脚本在其下创建文件夹 |
| 磁盘空间 | 目录本身占用很小,但如果要复制模板文件,需要关注模板体积 |
如果没有 Python 环境,Windows 用户可以直接用第 6 节给出的批处理或 PowerShell 方案。
3.3 跨平台工具选择
| 平台 | 推荐方式 | 理由 |
|---|---|---|
| Windows 日常 | PowerShell | 原生支持,参数解析清晰 |
| Windows 快速 | 批处理 bat | 不用装任何环境,逻辑简单 |
| macOS / Linux | Python | 跨平台,递归结构最容易表达 |
| 自动化服务器 | Python | 方便接入 CI 或定时任务 |
4. Python 实现:按模板批量创建并保留结构
这是本文的重点。我们用 Python 写一个通用脚本,模板用 JSON 表达,名单用 txt 文件表达,输出目录用命令行参数指定。
4.1 模板文件 config.json
JSON 嵌套结构适合表达多级目录。每一个 key 代表一个文件夹,空对象 {} 代表叶子目录。
json复制{
"docs": {
"raw": {},
"processed": {}
},
"data": {
"input": {},
"output": {}
},
"models": {},
"config": {}
}
这份模板表示最终每个文件夹下面会有:
text复制项目名/
├── docs/
│ ├── raw/
│ └── processed/
├── data/
│ ├── input/
│ └── output/
├── models/
└── config/
如果你想再加一级目录,直接在 JSON 里继续嵌套即可。
4.2 批量名单 names.txt
names.txt 每行一个名称,脚本会忽略空行。例如:
text复制2024-01
2024-02
2024-03
project_a
project_b
demo_001
这份名单最终会生成 6 套目录结构,每个目录内部都按 config.json 展开。
4.3 Python 核心脚本
python复制#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
按模板批量创建文件夹并保留结构
用法:python batch_create_folders.py config.json names.txt output_dir
"""
import json
import sys
from pathlib import Path
def load_template(config_path: str) -> dict:
"""读取 JSON 模板,返回目录结构树。"""
with open(config_path, "r", encoding="utf-8") as fp:
return json.load(fp)
def load_names(names_path: str):
"""读取名单文件,过滤空行和首尾空格。"""
with open(names_path, "r", encoding="utf-8") as fp:
return [line.strip() for line in fp if line.strip()]
def expand_node(base_path: Path, node: dict):
"""
递归展开模板结构。
base_path 是当前正在展开的目录,node 是当前层级的 JSON 子结构。
"""
for folder_name, child in node.items():
current = base_path / folder_name
current.mkdir(parents=True, exist_ok=True)
# 如果 child 是非空字典,继续递归创建子目录
if isinstance(child, dict) and child:
expand_node(current, child)
def create_one(output_dir: Path, name: str, template: dict):
"""为一个名称创建整套目录结构,返回目标根目录。"""
target = output_dir / name
target.mkdir(parents=True, exist_ok=True)
expand_node(target, template)
return target
def main():
if len(sys.argv) != 4:
print("用法:python batch_create_folders.py config.json names.txt output_dir")
sys.exit(1)
config_path, names_path, output_path = sys.argv[1], sys.argv[2], sys.argv[3]
template = load_template(config_path)
names = load_names(names_path)
output_dir = Path(output_path)
output_dir.mkdir(parents=True, exist_ok=True)
total = 0
for name in names:
create_one(output_dir, name, template)
total += 1
print(f"[OK] {output_dir / name}")
print(f"\n完成:本次一共创建 {total} 套目录结构。")
if __name__ == "__main__":
main()
这段代码已经做到:
- 递归展开 JSON 模板,任何层级都能保留;
- 自动创建缺失的父目录;
- 重复执行不会覆盖已有目录;
- 输出每一步的结果,方便核对。
4.4 运行命令与预期输出
把三个文件放到同一目录下:
text复制batch_create_folders.py
config.json
names.txt
然后执行:
bash复制python batch_create_folders.py config.json names.txt output
预期输出类似:
text复制[OK] output/2024-01
[OK] output/2024-02
[OK] output/2024-03
[OK] output/project_a
[OK] output/project_b
[OK] output/demo_001
完成:本次一共创建 6 套目录结构。
用 tree 查看结构:
bash复制tree output/2024-01
输出应该和模板完全一致:
text复制output/2024-01/
├── config/
├── data/
│ ├── input/
│ └── output/
├── docs/
│ ├── processed/
│ └── raw/
└── models/
如果看到某个子目录缺失,优先检查 JSON 模板是否缩进正确、文件名是否拼写错误。
5. 从现有模板目录批量复制结构
5.1 为什么需要“复制模板”
JSON 模板适合表达纯目录结构,但页面接收很多时候,你手里已经有一个标准的模板目录,里面除了子目录,还有初始文件,比如 README.md、.gitkeep、空白的配置文件。
这种情况下,直接用 Python 递归「复制模板目录」比手工解析 JSON 更省事。
5.2 使用 shutil.copytree 批量复制
python复制import shutil
from pathlib import Path
template_root = Path("./template")
output_dir = Path("./output")
names = ["item_001", "item_002", "item_003"]
for name in names:
target = output_dir / name
target.mkdir(parents=True, exist_ok=True)
shutil.copytree(template_root, target, dirs_exist_ok=True, copy_function=shutil.copy2)
print(f"[OK] {target}")
这里用 dirs_exist_ok=True 允许目标目录已存在,同时把模板里的文件和目录都复制进去。
5.3 空文件夹与 .gitkeep 处理
有一个常见问题:如果你把模板目录放进 Git 仓库,空目录不会被追踪。这样别人拉取模板仓库后,模板目录里没有空文件夹,复制出来的结构就缺目录。
解决办法是在空目录里放置一个 .gitkeep 占位文件:
text复制template/
├── docs/
│ ├── raw/
│ │ └── .gitkeep
│ └── processed/
│ └── .gitkeep
└── config/
└── .gitkeep
这样 copytree 会把 .gitkeep 一并复制过去,目录结构就完整保留下来了。
6. Windows 批处理与 PowerShell 实现
没有 Python 环境,Windows 上也能完成批量创建。有两种方式:批处理 bat 和 PowerShell,看需求选择。
6.1 Windows 批处理方案
在 names.txt 同目录下新建 batch_create_folders.bat:
bat复制@echo off
chcp 65001 >nul
setlocal
set "OUTPUT_DIR=output"
set "SUBDIRS=docs data config"
cd /d "%~dp0"
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"
if not exist "names.txt" (
echo 缺少 names.txt
exit /b 1
)
for /f "usebackq delims=" %%i in ("names.txt") do (
for %%d in (%SUBDIRS%) do (
mkdir "%OUTPUT_DIR%\%%i\%%d" 2>nul
)
echo [OK] %OUTPUT_DIR%\%%i
)
echo 批量创建完成
pause
运行后,每个名字都会在 output 下生成 docs、data、config 三个子目录。
需要注意:批处理里的子目录列表 SUBDIRS 是写死的,适合结构简单的场景。如果结构复杂、层级很深,建议用 PowerShell 或 Python。
6.2 PowerShell 方案
PowerShell 支持从结构文件读取模板,灵活度比 bat 更高。先准备一个 structure.txt:
text复制docs/raw
docs/processed
data/input
data/output
models
config
每行表示一个相对路径,脚本会按这些路径逐级创建。
然后创建 batch_create_folders.ps1:
powershell复制param(
[string]$TemplateFile = "structure.txt",
[string]$NameList = "names.txt",
[string]$OutputDir = "output"
)
$lines = Get-Content -Path $TemplateFile -Encoding UTF8 | Where-Object { $_.Trim() -ne "" }
$names = Get-Content -Path $NameList -Encoding UTF8 | Where-Object { $_.Trim() -ne "" }
New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null
foreach ($name in $names) {
$target = Join-Path $OutputDir $name
foreach ($line in $lines) {
$relativePath = $line.Trim().Replace("{name}", $name)
$fullPath = Join-Path $target $relativePath
New-Item -ItemType Directory -Force -Path $fullPath | Out-Null
}
Write-Host "[OK] $target"
}
Write-Host "批量创建完成"
执行:
powershell复制powershell -ExecutionPolicy Bypass -File .\batch_create_folders.ps1 -OutputDir output
这里加入 {name} 占位符后,模板路径也可以使用当前批量名称。比如 data/{name}/input,实际会创建 output/项目名/data/项目名/input,适合需要内部再按名称分层的场景。
6.3 两种方式对比
| 对比项 | 批处理 bat | PowerShell |
|---|---|---|
| 环境要求 | Windows 自带 | Windows 自带 |
| 模板灵活性 | 低,子目录列表固定 | 高,可从文件读取 |
| 中文支持 | 需要 chcp 65001 | 使用 UTF-8 读取 |
| 适合场景 | 快速、简单的固定结构 | 需要维护模板文件的场景 |
7. 高级批量创建与自动化扩展
7.1 结构模板中使用占位符
占位符的核心价值在于:模板结构里的某个子目录名可以跟随当前名称变化。PowerShell 方案里的 {name} 就是典型案例。
Python 也能实现同样的逻辑。把模板定义成相对路径列表,然后在创建时替换占位符:
python复制from pathlib import Path
structure_lines = [
"docs/raw",
"docs/processed",
"data/{name}/input",
"data/{name}/output",
]
output_dir = Path("output")
names = ["a", "b"]
for name in names:
target = output_dir / name
target.mkdir(parents=True, exist_ok=True)
for line in structure_lines:
line = line.replace("{name}", name)
path = target / line
path.mkdir(parents=True, exist_ok=True)
print(f"[OK] {target}")
这样每个项目目录内部还会再用自己的名称细分数据目录,在“多项目、多数据源”的场景中很实用。
7.2 日期序列、编号批量生成
如果不想维护长名单,可以按规则直接生成。
生成日期序列:
python复制from datetime import datetime, timedelta
start = datetime.strptime("2024-01-01", "%Y-%m-%d")
names = [(start + timedelta(days=i)).strftime("%Y-%m-%d") for i in range(30)]
生成编号序列:
python复制names = [f"project_{i:03d}" for i in range(1, 101)]
这样可以生成 001 到 100 的项目目录,和模板结构组合使用,配合前面 4.3 节的脚本就能直接批量创建。
7.3 接入定时任务和 CI
批量创建目录很适合接入计划任务。
Linux 用 cron:
cron复制0 2 * * * cd /opt/folder-batch && /usr/bin/python3 batch_create_folders.py config.json names.txt output
Windows 可以用任务计划程序调用:
bat复制python D:\folder-batch\batch_create_folders.py D:\folder-batch\config.json D:\folder-batch\names.txt D:\folder-batch\output
接入 CI 时,可以在流水线开始前执行目录初始化。注意控制输出日志,不要在生产流水线里打印过多中间过程。
8. 接口 API 与批量任务设计
8.1 命令行接口
目前这个工具的核心接口是命令行:
bash复制python batch_create_folders.py <config.json> <names.txt> <output_dir>
三个参数分别是模板文件、名单文件和输出目录。命令行接口的好处是容易集成,也容易手动测试。
8.2 将脚本包装为 HTTP 接口
如果要把批量创建能力开放给内部系统调用,可以用 FastAPI 简单包装。以下代码只是通用示例,实际项目中的鉴权、限流和端口配置需要按你的环境调整。
python复制from fastapi import FastAPI
from pydantic import BaseModel
from pathlib import Path
import batch_create_folders as bcf
app = FastAPI()
class CreateRequest(BaseModel):
config_file: str = "config.json"
output_dir: str = "output"
names: list[str] = []
@app.post("/api/create_folders")
def create_folders(req: CreateRequest):
template = bcf.load_template(req.config_file)
output_dir = Path(req.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
created = []
for name in req.names:
target = bcf.create_one(output_dir, name, template)
created.append(str(target))
return {"code": 0, "created": created}
启动服务需要用 uvicorn:
bash复制uvicorn server:app --host 127.0.0.1 --port 8000
调用示例:
python复制import requests
url = "http://127.0.0.1:8000/api/create_folders"
payload = {
"config_file": "config.json",
"output_dir": "output",
"names": ["client_01", "client_02", "client_03"]
}
response = requests.post(url, json=payload, timeout=30)
print(response.json())
前面 4.3 节的函数 load_template 和 create_one 本来就是独立函数,所以复用起来很顺。
8.3 批量任务失败处理建议
批量创建目录本身失败概率不高,但如果接入自动化,建议做好三点:
- 每次任务输出一份创建清单,方便后续核对;
- 批量名称列表每批控制在合理数量,避免一次性处理太多导致中途权限报错;
- 失败时保留日志,打印具体名称,方便定位。
目录创建是 I/O 操作,出错原因大多是权限、非法字符和路径过长,逐个排查即可。
9. 资源占用与性能观察
批量创建文件夹不是计算密集任务,但也不是完全没有性能问题。
9.1 批量创建的影响因素
- 文件系统类型:NTFS、APFS、ext4 的批量创建性能有差异;
- 磁盘类型:SSD 比机械硬盘快很多;
- 目录深度:层级越深,文件系统元数据操作越多;
- 杀毒软件实时扫描:某些 Windows 环境下,安全软件对目录创建的拦截会拖慢速度;
- 路径长度:过长的路径在部分系统上会显著变慢甚至失败。
如果你的批次规模很大,比如一次创建上千套目录,先做小批量测试,再逐步放大。
9.2 性能观察方法
Linux 和 macOS 可以用 time 观察:
bash复制time python batch_create_folders.py config.json names.txt output
Windows PowerShell 可以用:
powershell复制Measure-Command { python batch_create_folders.py config.json names.txt output }
不需要追求极端速度,重点看两个指标:总体耗时和是否出现失败项。
9.3 降低 IO 开销
如果确实要创建大量目录,可以注意:
- 使用成熟文件系统,避免在网盘同步目录里高频创建目录;
- 大批量目录不要直接在 Windows 资源管理器里实时刷新,容易卡;
- 输出结果分目录管理,不要把所有批次都堆到同一个根目录,避免单个目录下目录数量过大;
- 临时性测试用
tmp或output_test目录,不要污染正式目录。
10. 功能测试与效果验证
10.1 最小化测试
第一次运行,先用 3 到 5 个名称测试,模板也尽量用简单结构。
text复制2024-01
project_a
demo_001
确认输出正常后,再扩大名单。
10.2 目录树对比验证
以「JSON 模板递归创建」为例,检查单个目录:
bash复制tree output/2024-01
输出应该和模板结构完全一致。要批量校验,可以提取所有目录相对路径,排序后再和模板做 diff。
比如,把 expected 结构写进 expected_tree.txt:
text复制config
data/input
data/output
docs/processed
docs/raw
models
然后对比:
bash复制cd output/2024-01
find . -type d | sed 's|^\./||' | sort > actual_tree.txt
diff expected_tree.txt actual_tree.txt
没有输出说明结构完全一致。
10.3 幂等性验证
批量创建脚本通常具备幂等性:同一条命令执行第二次,不会覆盖已有目录,也不会产生重复错误。
测试方式:
bash复制python batch_create_folders.py config.json names.txt output
python batch_create_folders.py config.json names.txt output
第二次执行后,检查目录内容没有变化,新目录不会重复创建,已经存在的目录不会被破坏。这种特性在自动化任务里非常有用。
11. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
提示 ModuleNotFoundError |
缺少第三方库 | 检查 Python 环境 | 本方案标准库即可,不需要额外依赖 |
| Windows 批处理中文乱码 | 默认代码页不对 | 检查输出信息 | 使用 chcp 65001 >nul |
| 目录创建时提示路径已存在 | 目标目录已存在 | 检查脚本是否做过存在判断 | exist_ok=True,重复执行默认跳过 |
| 名单里有空行导致异常 | 文件存在空白行 | 查看 names.txt |
加载时过滤空行 |
名称包含 <>:"/\|?* |
Windows 路径非法字符 | 打印具体名称 | 增加命名校验,生成前清洗 |
| 文件路径超过系统限制 | Windows 长路径问题 | 查看提示信息 | 启用长路径支持,或缩短结构层级 |
| 中文文件夹在 Git 中显示异常 | 编码不一致 | 检查模板文件编码 | 统一保存为 UTF-8 |
copytree 复制后缺少空目录 |
Git 不追踪空目录 | 拉取模板后检查 | 在空目录加入 .gitkeep 占位文件 |
| 权限不足 | 输出目录不支持写操作 | 手动创建测试目录 | 更换输出根目录或提升权限 |
12. 最佳实践与使用建议
12.1 脚本和模板分开维护
脚本只负责“读模板、建目录”,模板负责“定义结构”。这样后续改目录层级,只需要改 config.json 或 structure.txt,不需要动代码。
12.2 先小批次,再大批量
任何新脚本第一次运行都用小名单。确认模板和输出路径都没问题,再上完整名单。免得一次建错几百个目录,再手动清理。
12.3 输出日志和创建报告
生产环境建议把输出保存成日志文件:
bash复制python batch_create_folders.py config.json names.txt output > run.log 2>&1
也可以让脚本在结束后把成功目录名写入 created.txt,方便追溯。
12.4 命名要统一、安全
- 使用英文小写、数字、下划线或者短横线;
- 避免空格和特殊字符;
- 中文名可以使用,但要注意跨平台兼容性;
- 不要用客户手机号、身份证号做目录名;
- 批量命名前需要确认命名规则符合团队规范。
12.5 重要目录不要直接覆盖
脚本里要有“已存在即跳过”的默认逻辑。如果某个名称已经存在完整结构,保持原样。除非有明确需求,否则不要增加强制删除选项。
12.6 涉及文件复制时注意版权与授权
如果模板目录里有配置文件、软件包或素材文件,复制前要确认这些内容允许批量分发。涉及版权素材、内部资料或客户数据时,必须确认授权边界,不能因为只是“复制文件夹”就忽略合规问题。
13. 总结与下一步
按模板批量创建文件夹,最有价值的地方不是省几分钟,而是让目录结构可控。模板定义好后,任何一次批量创建,生成结果都稳定一致,不会出现有人多建一级目录、有人漏建的情况。
建议第一次验证以下三个点:
- 用 5 个名称跑通 JSON 模板脚本;
- 用
tree对比生成结果是否和模板一致; - 重复运行一次,确认幂等性正常。
最容易踩的坑有两个:一是模板 JSON 写错,导致子目录层级缺失;二是 Windows 下中文编码问题,导致 bat 输出乱码。遇到就用第 11 节的排查表对照处理。
下一步可以做的事:
- 把常用结构抽成多个模板文件,例如
project.json、archive.json、client.json; - 把脚本接入定时任务,每天自动生成日期目录;
- 将批量创建封装成内部 HTTP 接口,方便给团队工具调用。
建议收藏备用。下次需要批量建目录时,直接复制脚本,改一份模板,就能跑完整个批量创建任务。
