2009-11-09 86 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)