You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将循环遍历的文件路径传入仅接受原始字符串的函数?

问题:Shell.NameSpace无法接收变量路径获取文件元数据

背景

我正在写一个生成目录内容报告的脚本,输出为CSV格式,每份报告用唯一时间戳命名,避免覆盖或追加到同一文件。报告的列头是:

header = ['File_Pathway', 'Subdir', 'File_Name', 'Extension', 'Size_(in_bytes)', 'File_Created', 'Last_File_Save_Date', 'File_Author', 'Last_Saved_By_User_X']

其中File_Author和Last_Saved_By_User_X这两个字段一直拿不到,后来找到一段通过文件元数据收集信息的脚本:

import win32com.client
sh=win32com.client.gencache.EnsureDispatch('Shell.Application',0)
ns = sh.NameSpace(r'm:\music\Aerosmith\Classics Live!')
colnum = 0
columns = []
while True:
    colname=ns.GetDetailsOf(None, colnum)
    if not colname:
        break
    columns.append(colname)
    colnum += 1

for item in ns.Items():
    print (item.Path)
    for colnum in range(len(columns)):
        colval=ns.GetDetailsOf(item, colnum)
        if colval:
            print('\t', columns[colnum], colval)

遇到的问题

这段脚本里sh.NameSpace用的是原始字符串写法,但我需要传入遍历目录时的current_filepath变量。试了各种把字符串转成原始字符串的方法都没用,求解决。

附上我脚本里current_filepath的相关代码片段:

rootdir = input('Enter directory pathway: ')
count = 0

datetime_for_filename = datetime.now()
datetime_for_filename_format = str(datetime.strftime(datetime_for_filename, '%Y-%m-%d--%H-%M-%S'))
 
filename_with_datetimestamp = 'filename_printout' + '-' + datetime_for_filename_format + '.csv'

header = ['File_Pathway', 'Subdir', 'File_Name', 'Extension', 'Size_(in_bytes)', 'File_Created', 'Last_File_Save_Date', 'File_Author', 'Last_Saved_By_User_X']
    
for subdir, dirs, files in os.walk(rootdir):
    with open(filename_with_datetimestamp, 'a', newline='') as f:
        writer = csv.writer(f)
        current_subdir = subdir
        try:
            for filenames in files:
                data_list = []
                current_filepath = subdir +  '\\' + filenames
                raw_current_filepath = fr"{current_filepath}"

解决方法

先说清楚:sh.NameSpace根本不需要原始字符串,它接受普通字符串路径。原始字符串只是写代码时为了避免转义的写法,变量本身就是字符串,直接传就行。真正的问题是你传错了路径类型——它要的是目录路径,不是单个文件路径!

修正后的完整代码示例

import win32com.client
import os
import csv
from datetime import datetime

def get_file_metadata(file_path):
    sh = win32com.client.gencache.EnsureDispatch('Shell.Application')
    # 获取文件所在的目录路径
    dir_path = os.path.dirname(file_path)
    ns = sh.NameSpace(dir_path)
    if not ns:
        return None
    
    # 先枚举当前目录所有可用的元数据列
    columns = []
    colnum = 0
    while True:
        colname = ns.GetDetailsOf(None, colnum)
        if not colname:
            break
        columns.append(colname)
        colnum += 1
    
    # 在目录项中找到目标文件
    file_name = os.path.basename(file_path)
    file_item = None
    for item in ns.Items():
        if item.Name == file_name:
            file_item = item
            break
    
    if not file_item:
        return None
    
    # 提取需要的元数据
    metadata = {}
    for colnum in range(len(columns)):
        colval = ns.GetDetailsOf(file_item, colnum)
        if colval:
            metadata[columns[colnum]] = colval
    
    return metadata

# 主脚本逻辑
rootdir = input('请输入目录路径: ')
datetime_for_filename = datetime.now()
datetime_for_filename_format = datetime.strftime(datetime_for_filename, '%Y-%m-%d--%H-%M-%S')
filename_with_datetimestamp = f'filename_printout-{datetime_for_filename_format}.csv'

header = ['File_Pathway', 'Subdir', 'File_Name', 'Extension', 'Size_(in_bytes)', 'File_Created', 'Last_File_Save_Date', 'File_Author', 'Last_Saved_By_User_X']

# 先写入CSV表头(只写一次)
with open(filename_with_datetimestamp, 'w', newline='', encoding='utf-8-sig') as f:
    writer = csv.writer(f)
    writer.writerow(header)

# 遍历目录所有文件
for subdir, dirs, files in os.walk(rootdir):
    for filename in files:
        current_filepath = os.path.join(subdir, filename)
        data_list = []
        
        # 填充基础文件信息
        data_list.append(current_filepath)
        data_list.append(subdir)
        data_list.append(filename)
        # 提取扩展名(去掉开头的点)
        ext = os.path.splitext(filename)[1]
        data_list.append(ext[1:] if ext else '')
        data_list.append(os.path.getsize(current_filepath))
        # 转换时间格式为可读字符串
        data_list.append(datetime.fromtimestamp(os.path.getctime(current_filepath)).isoformat())
        data_list.append(datetime.fromtimestamp(os.path.getmtime(current_filepath)).isoformat())
        
        # 获取元数据并提取作者和最后保存人
        metadata = get_file_metadata(current_filepath)
        # 注意:元数据列名随系统语言变化,中文系统可能是"作者"、"最后保存者",英文是"Author"、"Last Saved By"
        file_author = metadata.get('Author', '') if metadata else ''
        last_saved_by = metadata.get('Last Saved By', '') if metadata else ''
        
        data_list.append(file_author)
        data_list.append(last_saved_by)
        
        # 写入CSV行
        with open(filename_with_datetimestamp, 'a', newline='', encoding='utf-8-sig') as f:
            writer = csv.writer(f)
            writer.writerow(data_list)

关键注意点

  1. 路径传递问题:sh.NameSpace必须传目录路径,不能传单个文件路径,所以要先用os.path.dirname()从文件路径中提取目录
  2. 原始字符串误区:变量形式的字符串不需要转成原始字符串,直接传就行,原始字符串只是写死路径时的语法糖
  3. 路径拼接:用os.path.join()替代手动拼接+ '\\',避免跨系统路径分隔符问题
  4. 表头写入:表头只需要写入一次,不要放在循环里反复打开文件追加
  5. 元数据列名:列名会随系统语言变化,比如中文系统里"Author"会变成"作者",需要根据自己的系统调整字典的键名

内容的提问来源于stack exchange,提问作者Katherine Jarzecki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 23:30:48