Python文件操作

1 投票
3 回答
1908 浏览
提问于 2025-04-15 15:48

假设我有这样的文件夹结构:

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

在我的根文件夹下,每个子文件夹代表一个月份,比如 01、02、03。在这些子文件夹里,我有一些文件,它们的命名方式是根据创建的小时和文件名,比如 16_item1.xml、24_item1.xml 等等。你可以猜到,这里有好几个文件,每个文件都是每小时创建的。

现在我想做两件事:

  • 我需要生成一个某个月的文件名列表,比如在 01 这个文件夹里,我有 item1、item2 和 item3。

  • 我需要对每个文件进行筛选,比如对于 item1,我想读取从 01_item1.xml 到 24_item1.xml 的所有文件。

我该如何用 Python 轻松实现这些呢?

3 个回答

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)] 这行代码会生成从01到12的文件夹名称。

filenames = ["%02d"%i for i in range(1,24)] 这行代码会生成从01到23的文件名。


使用 os.path.join 来构建复杂的路径,这比简单的字符串拼接要好。

os.path.join(foldername,filename)

os.path.exists 来检查一个文件是否存在。

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

如果你想列出目录里的内容,可以使用 glob

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

使用 shutil 来进行更高级的操作,比如创建文件夹或重命名文件。

shutil.move(oldname,newname) 这行代码可以用来移动或重命名文件。


basename 可以从完整路径中提取出文件名。

filename = os.path.basename(fullpath) 这行代码会得到文件的名字。

5

这里有两种方法可以实现你想要的功能(如果我理解正确的话)。一种是用正则表达式,另一种则不使用。你可以选择你喜欢的那种;)

有一点可能看起来像魔法的就是“setdefault”这一行。想要了解它的具体含义,可以查看这个文档。我把理解它的过程留给你自己去探索;)

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"] ) )

撰写回答