2009-11-09 55 views
1

假设我有这样的文件夹Python的文件操作

rootfolder 
     | 
    /\ \ 
    01 02 03 .... 
    | 
    13_itemname.xml 

所以我rootfolder下,每个目录代表了一个月像01 02 03,并在这些目录我有自己的创造小时,项目名称 如16_item1项目.xml,24_item1.xml等,你可能会猜测有几个项目,每个小时创建每个xml。

现在我要做两件事情:

  • 我需要生成项目名称的列表一个月,即对于01我有物品1,ITEM2和项目3中。

  • 我需要筛选每个项目,比如item1:我想从01_item1.xml中读取每个项目到24_item1.xml。

如何以简单的方式在Python中实现这些目标?

+0

什么代码,你现在有吗?这不是“为me.com写我的代码”。你尝试了什么?当你看着'os.walk'时,你看到了什么? – 2009-11-09 11:09:52

回答

5

这里有两种方法正在做你所问(如果我正确地理解它)。一个与正则表达式,一个没有。你选择哪一个你喜欢;)

看起来像魔术的一点是“setdefault”行。有关说明,请参见the docs。我把它作为“练习读者”,以了解它是如何工作的;)

from os import listdir 
from os.path import join 

DATA_ROOT = "testdata" 

def folder_items_no_regex(month_name): 

    # dict holding the items (assuming ordering is irrelevant) 
    items = {} 

    # 1. Loop through all filenames in said folder 
    for file in listdir(join(DATA_ROOT, month_name)): 
     date, name = file.split("_", 1) 

     # skip files that were not possible to split on "_" 
     if not date or not name: 
     continue 

     # ignore non-.xml files 
     if not name.endswith(".xml"): 
     continue 

     # cut off the ".xml" extension 
     name = name[0:-4] 

     # keep a list of filenames 
     items.setdefault(name, set()).add(file) 

    return items 

def folder_items_regex(month_name): 

    import re 

    # The pattern: 
    # 1. match the beginnning of line "^" 
    # 2. capture 1 or more digits (\d+) 
    # 3. match the "_" 
    # 4. capture any character (as few as possible): (.*?) 
    # 5. match ".xml" 
    # 6. match the end of line "$" 
    pattern = re.compile(r"^(\d+)_(.*?)\.xml$") 

    # dict holding the items (assuming ordering is irrelevant) 
    items = {} 

    # 1. Loop through all filenames in said folder 
    for file in listdir(join(DATA_ROOT, month_name)): 

     match = pattern.match(file) 
     if not match: 
     continue 

     date, name = match.groups() 

     # keep a list of filenames 
     items.setdefault(name, set()).add(file) 

    return items 
if __name__ == "__main__": 
    from pprint import pprint 

    data = folder_items_no_regex("02") 

    print "--- The dict ---------------" 
    pprint(data) 

    print "--- The items --------------" 
    pprint(sorted(data.keys())) 

    print "--- The files for item1 ---- " 
    pprint(sorted(data["item1"])) 


    data = folder_items_regex("02") 

    print "--- The dict ---------------" 
    pprint(data) 

    print "--- The items --------------" 
    pprint(sorted(data.keys())) 

    print "--- The files for item1 ---- " 
    pprint(sorted(data["item1"])) 
+0

非常感谢代码! – Hellnar 2009-11-09 08:11:10

+0

不客气。我只是稍微编辑了一下。看一看。它可能不太可读,但它可能表现更好(只是一种直觉)。 – exhuma 2009-11-09 08:12:56

+0

*非常重要*:上面的代码包含一个错误。如果项目名称包含“_”,则代码将与“解包太多的值”打破(我认为这是它给出的消息)。我为“split”调用添加了“maxsplit”参数。这将防止错误。 – exhuma 2009-11-09 08:18:16

0

假设项目名称有一个固定长度的前缀和后缀(即3字符前缀,如“01_”和4个字符后缀的'.xml'),你可以像这样解决问题的第一部分:

names = set(name[3:-4] for name in os.listdir('01') if name.endswith('.xml')] 

这会得到你独特的项目名称。

要过滤每个项目,只需查找以该项目名称结尾的文件并根据需要对其进行分类。

item_suffix = '_item2.xml' 
filtered = sorted(name for name in os.listdir('01') if name.endswith(item_suffix)) 
0

不知道你想要什么做的,但这里有一些指针可能是


创建文件名非常有用(“%02D”是指垫留下了零)

foldernames = ["%02d"%i for i in range(1,13)]

filenames = ["%02d"%i for i in range(1,24)]


使用os.path.join的建立,而不是字符串连接

os.path.join(foldername,filename) 

os.path中复杂的路径。存在检查文件是否存在第一

if os.path.exists(newname): 
    print "file already exists" 

上市目录的内容,使用水珠

from glob import glob 
xmlfiles = glob("*.xml") 

使用shutil更高级别的操作,如创建文件夹,重命名文件

shutil.move(oldname,newname)


基名从一个完整的路径获取文件名

filename = os.path.basename(fullpath)