根据文件名中嵌入的时间戳对文件进行排序、分组和处理

2024-09-29 21:27:20 发布

您现在位置:Python中文网/ 问答频道 /正文

如何按照嵌入在每个文件名中的日期字符串对这些文件进行排序?然后我想循环查看当天创建的所有文件

我可以在壳里做这个,但是速度很慢。我想用python做同样的事情

示例文件列表(共有2200个文件)

  1. 泰勒·考恩阅读202109200657.md
  2. 论诗歌202109210659.md
  3. Slava Akhmechet关于集群阅读202109200659.md
  4. 4X4矩阵202109200717.md中的构思
  5. 图纸网格构思202109220830.md
  6. 听写201208251425.md

输出如下所示(用于最终绘制Plotly。)

20120825,1  
20210920,3  
20210921,1  
20210922,1  

我想按给定日期的文档计数排序,然后按日期在文档计数内排序。因此,上述结果1、3和4将按日期顺序列出:

20210920,3
20120825,1  
20210921,1  
20210922,1  

然后我想用每天的文档做其他事情,比如获取当天的总字数


Tags: 文件字符串文档示例列表排序文件名事情
3条回答

这是我理解的任务清单

  1. 从文件名字符串和列表处理中提取字符串时间戳

  2. 将时间戳(包括小时、分钟、秒)标准化为日期戳(仅限年-月-日),以便在单日日期处理上对文档进行分组

  3. 按每天文档数降序排序,然后在每天文档数内按日期升序稳定排序

  4. 在同一日期对文档进行分组,以某种方式将函数传递给其他函数进行处理

这涵盖了Python编程中相当多的基础知识,因此我将在接下来的过程中进行解释

我建议使用arrow库来处理日期。 首先,安装箭头:

pip install arrow

import itertools
from collections import Counter
from pathlib import Path

import arrow

docs = [
    'Tyler Cowen On Reading 202109200657.md',
    'On Poems 202109210659.md',
    'Slava Akhmechet On Reading In Clusters 202109200659.md',
    'Ideation In A 4X4 Matrix 202109200717.md',
    'Drawing Grid Ideation 202109220830.md',
    'Dictation 201208251425.md',
]


def datestamp(filename):
    basename = Path(filename).stem
    date_as_string = basename.split()[-1]
    timestamp = arrow.get(date_as_string, 'YYYYMMDDhhmm')
    return timestamp.format('YYYYMMDD')

要从文件名中提取日期部分,您需要文档“基本名称”的最后一部分,位于最后一个空格之后

Python的.split()方法将字符串拆分为一个空白列表(空格、制表符等):

>>> basename = 'On Poems 202109210659'
>>> basename.split()
['On', 'Poems', '202109210659']

a_list[-1]提取列表中的最后一项,因此:


>>> basename.split()[-1]
'202109210659'

获取时间戳最后一个空格后文件的basename中的所有内容

然后arrow用于将时间戳转换为日期戳,因此忽略文档时间,并将当天的文档分组在一起

202109210659 -> 20210921

使用arrow而不是regex意味着您可以处理文件名中的不同日期格式

在本例中,将日期排序为字符串是有效的,因为所有日期都采用YMD格式,年份(最大的部分)后跟月份和日期。如果我们对DMY日期进行排序,我们会得到意想不到的结果

对于Plotly数据:

datestamps = [datestamp(doc) for doc in docs]
datestamps.sort()
docDates = Counter()
for date in datestamps:
    docDates[date] += 1
for date, doc_count in docDates.most_common():
    print(f'{date},{doc_count}')

Counter()是Python标准库中的一个有用类。 它的.most_common()方法用于首先对文档最多的日期进行排序:

>>> python docs.py
20210920,3
20120825,1
20210921,1
20210922,1

请注意,1-doc日期是按日期排序的第二级日期。datestamps.sort()(在.most_common()之前)是第二级按日期排序,因为Python库排序函数是“稳定的”。在Counter()上迭代遵循原始插入顺序,因此.most_common()将在文档计数相同的情况下保留从datestamps.sort()开始的原始日期顺序

为了更好地理解稳定排序,see this answer。你可能需要花一些时间去理解它

要对共享给定日期的文档进行分组,请首先使用datestamp函数对文档进行排序,然后使用相同的函数对文档进行分组。这使您可以处理与单个日期相关的所有文档(用于每日字数统计等)。会为每个文件名计算datestamp“key”函数,然后在排序和分组时用于比较项目

docs.sort(key=datestamp)
for date, docs_on_date in itertools.groupby(docs, key=datestamp):
    docs_today = list(docs_on_date)
    print(f'{date}: {docs_today}')
    # for doc in docs_today:
    #     # do_something_with(doc)

结果:

20120825: ['Dictation 201208251425.md']
20210920: ['Tyler Cowen On Reading 202109200657.md', 'Slava Akhmechet On Reading In Clusters 202109200659.md', 'Ideation In A 4X4 Matrix 202109200717.md']
20210921: ['On Poems 202109210659.md']
20210922: ['Drawing Grid Ideation 202109220830.md']

如果您试图替换shell脚本,那么您的Python脚本可能需要执行以下操作

  1. 列出目录的内容以获取文件名
  2. 从文件名中提取日期(假设正则表达式模式匹配\d{8}足以提取日期)
  3. 按提取日期对文件进行排序或分组
  4. 迭代这些组以执行某些操作
import pathlib
import re
from collections import defaultdict

date_pattern = re.compile(r"\d{8}")
target_dir = pathlib.Path("myfolder")

# Files is a dictionary mapping a date to the list of files with that date
files = defaultdict(list)
for child in target_dir.iterdir():
    # Skip directories
    if child.is_dir():
        continue
    match = date_pattern.search(child.name)
    # Skip files that do not match the date pattern
    if match is None:
        continue
    file_date = match.group()
    files[file_date].append(child)

for date, names in files.items():
    for filename in names:
        # Do something
        print(date, filename)

编辑:按日期排序

要按日期排序,可以修改最后一个代码块

for date in sorted(files):
    for filename in files[date]:
        # Do something
        print(date, filename)

您也可以使用for date, names in sorted(files.items(), key=lambda d: d[0]):

这是你需要的吗?下面的代码从每个文件中提取日期,并将其附加到字典中,其中日期是键,因此字典的格式为:

{
date1: [list of files],
date2: [list of files]
}

代码如下:

from collections import defaultdict
import re
files = ['Tyler Cowen On Reading 202109200657.md',
'On Poems 202109210659.md',
'Slava Akhmechet On Reading In Clusters 202109200659.md',
'Ideation In A 4X4 Matrix 202109200717.md',
'Drawing Grid Ideation 202109220830.md',
'Dictation 201208251425.md']

out = defaultdict(list)
for file in files:
    date = re.search(r'.*\s(\d+).md', file)
    if date:
        date = date.group(1)[:8]
        out[date].append(file)
print (out)

输出:

defaultdict(<class 'list'>, {'20210920': ['Tyler Cowen On Reading 202109200657.md', 'Slava Akhmechet On Reading In Clusters 202109200659.md', 'Ideation In A 4X4 Matrix 202109200717.md'], '20210921': ['On Poems 202109210659.md'], '20210922': ['Drawing Grid Ideation 202109220830.md'], '20120825': ['Dictation 201208251425.md']})

请注意,这段代码只是给出了逻辑,并没有得到目录中的文件列表,您只需要创建一个所有必需文件的列表,并在上面的代码中使用该列表

相关问题 更多 >

    热门问题