SharePoint按文件名前缀创建子文件夹分类存储文件方案咨询
你遇到的[WinError 5] Access is denied报错,本质是本地OneDrive同步的SharePoint路径默认开启「按需文件」功能,文件/文件夹是虚拟重定向路径,Python标准os库无法直接对这类路径执行写入、创建操作,和你本身的代码逻辑无关。
你的需求完全可以通过两种方案实现,具体如下:
方案一:Python实现(适合有脚本维护能力的场景)
核心技术方向
不要直接操作本地同步盘路径,直接对接SharePoint云端接口操作文件,从根源绕过本地同步层的权限限制:
- 依赖库选择:使用
Office365-REST-Python-Client库封装的SharePoint REST接口完成认证、文件列表拉取、文件夹创建、文件移动操作 - 认证方式:测试阶段可以直接使用你的Office365账号密码认证,生产环境建议找站点管理员申请应用注册权限,使用客户端ID+密钥认证,避免个人账号密码过期导致脚本失效
- 原有逻辑可以直接复用:读取Excel拿到合法资产ID列表、拉取目标目录所有文件、按
_分割文件名提取前缀资产ID、匹配到合法资产且不存在对应文件夹时创建文件夹、最后移动对应文件到目标路径 - 如果一定要走本地路径操作:先右键本地同步的SharePoint目标文件夹,勾选「始终保留在此设备上」关闭虚拟文件功能,再替换
os库的文件操作为shutil库,但是这种方式稳定性差,容易出现同步冲突、文件锁问题,不推荐生产使用。
参考核心代码
from office365.sharepoint.client_context import ClientContext from office365.runtime.auth.user_credential import UserCredential import openpyxl from io import BytesIO # 配置参数 site_url = "https://公司域名.sharepoint.com/sites/目标站点名" username = "你的工作账号" password = "你的账号密码" target_library = "Shared Documents/Video" # 目标文档库相对路径 excel_relative_path = "Shared Documents/Automation/assets.xlsx" # Excel存放在SharePoint的相对路径 # 认证连接 ctx = ClientContext(site_url).with_credentials(UserCredential(username, password)) # 1. 读取Excel拿到合法资产ID列表 excel_file = ctx.web.get_file_by_server_relative_url(excel_relative_path).download().execute_query() wb = openpyxl.load_workbook(BytesIO(excel_file.content), data_only=True) # 如果Excel存在本地,直接替换为wb = openpyxl.load_workbook("本地Excel路径", data_only=True)即可 sheet = wb['assets'] valid_asset_ids = [sheet.cell(row,1).value for row in range(2, sheet.max_row+1) if sheet.cell(row,2).value is not None] # 2. 拉取目标目录下所有现有文件、文件夹 target_folder = ctx.web.get_folder_by_server_relative_url(target_library) files = target_folder.files.get().execute_query() existing_folders = [f.name for f in target_folder.folders.get().execute_query()] # 3. 遍历文件创建文件夹、移动文件 created_folder_count = 0 moved_file_count = 0 for file in files: asset_id = file.name.split('_')[0] # 跳过非合法资产的文件 if asset_id not in valid_asset_ids: continue # 不存在对应资产文件夹则创建 if asset_id not in existing_folders: target_folder.folders.add(asset_id).execute_query() existing_folders.append(asset_id) created_folder_count +=1 # 移动文件到对应资产文件夹,参数1表示覆盖同名文件 target_path = f"{target_library}/{asset_id}/{file.name}" file.moveto(target_path, 1).execute_query() moved_file_count +=1 print(f"执行完成,共创建{created_folder_count}个文件夹,移动{moved_file_count}个文件")
注意:使用前先执行pip install Office365-REST-Python-Client openpyxl安装依赖
方案二:Power Automate实现(无代码,推荐日常运维使用)
你持有官方许可的情况下,这个方案不需要写代码、不需要维护脚本运行环境,稳定性更高,搭建步骤如下:
- 新建计划云端流,设置触发周期为每日固定时间(建议设置在现场团队完成每日数据上传的时间点之后,比如每日凌晨2点)
- 添加「列出表中存在的行」动作,关联存储资产列表的Excel文件(Excel需要存放在SharePoint/OneDrive路径下,不支持本地路径文件),读取所有合法资产ID
- 添加「列出文件夹」动作,关联SharePoint站点的Video目标文件夹,获取目录下所有文件、子文件夹列表
- 添加「应用到每一个」循环,遍历所有获取到的文件项:
- 用表达式
split(items('应用到每一个')?['{Name}'], '_')[0]提取当前文件名前缀的资产ID - 添加条件判断:提取到的资产ID在Excel合法资产列表中,且当前Video目录下不存在同名子文件夹
- 条件满足时,添加「创建新文件夹」动作,创建路径为Video目录+资产ID
- 最后添加「移动文件」动作,将当前文件移动到对应资产ID的子文件夹下,可配置覆盖同名文件规则
- 用表达式
- 可选配置:流执行末尾添加「发送电子邮件」动作,将本次执行创建的文件夹数量、移动文件数量发送到你的邮箱,方便每日核对结果。
内容的提问来源于stack exchange,提问作者Merkator
相关产品推荐
相关产品推荐

