【问题标题】:Sort files by numerical order while excluding files with non-numeric filenames按数字顺序对文件进行排序,同时排除具有非数字文件名的文件
【发布时间】:2021-01-18 06:17:25
【问题描述】:

我在一个目录中有一堆文件,我想从中选择 CSV 文件并对它们进行数字排序,因为稍后我将根据数字顺序应用一些处理。但是,其中一些文件具有非数字文件名;我想忽略这些,只对名称完全为数字的文件进行排序和检索(例如,取5.csv,但忽略data5.csv.DS_Store)。

以我的文件夹结构为例,我的文件名如下所示:1.csv, 1.txt, 10.csv, 2.csv, 3.csv, .DS_Store。从那些我想产生以下排序输出: 1.csv, 2.csv, 3.csv, 10.csv 并为非 CSV 文件或具有非数字名称的其他文件打印一条错误消息。

我试图通过向sorted 函数添加一个键并使用os.scandir() 来实现这一点。这是一个最小的例子。

import os

def get_csv_files(path):
    """
    Generator function to sort and yield the CSV files with numerical filenames.

    Arguments:
        path: Path to the directory containing the CSV files.
    Returns:
        Paths of the found CSV files.
    """
    for entry in sorted(os.scandir(path), key=lambda e: int(os.path.splitext(e.name)[0])):
        if entry.is_file() and entry.name.endswith(".csv"):
            yield entry.path
        elif entry.is_dir():
            yield from get_csv_files(entry.path)
        else:
            print(f"Neither a csv file, nor a dir: {entry.path}")

path = '/path/to/dataset'
for i, file in enumerate(get_csv_files(path)):
    print(file)

如果文件名仅包含数字,则此方法可以正常工作,否则会失败并出现以下错误(对于上面给出的文件名):

ERROR with .DS_Store
  File "test.py", line 12, in <lambda>
     for entry in sorted(os.scandir(path), key=lambda e: int(os.path.splitext(e.name)[0])):
 ValueError: invalid literal for int() with base 10: '.DS_Store'

我了解该错误是由于我的代码尝试将字符串 .DS_Store 转换为 int 造成的,这显然是错误的行为,但我无法弄清楚如何进行排序。我需要一种方法来从排序键中排除不需要的文件名,并且可能需要操作 lambda 函数。

【问题讨论】:

    标签: python sorting


    【解决方案1】:

    试试这个:

    import os
    
    path = "/absolute/path/to/files/to/sort/"
    numerical_files = []
    for f in os.listdir(path):
        file_name, extension = f.split('.')
        if extension == "csv" and file_name.isnumeric():
            numerical_files.append(file_name)
        else:
            print("Invalid file: ", f)
    
    numerical_filenames_ints = [ int(f) for f in numerical_files ]
    numerical_filenames_ints.sort()
    
    for f in numerical_filenames_ints:
        file = str(f) + ".csv"
        print(file)
    
    

    【讨论】:

    • 如果目录中有一个文件名中包含多个.,则file_name, extension = f.split('.') 行将引发ValueError: too many values to unpack (expected 2),如果目录中有一个文件名为ValueError: not enough values to unpack (expected 2, got 1),则该行将引发名称中没有.
    • 另请注意,使用numerical_filenames_ints = [int(f) for f in numerical_files]; numerical_filenames_ints.sort() 代替numerical_files.sort(key=int) 可能会修改文件名;例如,034.csv 将更改为 34.csv
    【解决方案2】:

    添加此功能:

    def listdir_nohidden(path):
        for f in os.listdir(path):
            if not f.startswith('.'):
                yield f
    

    并更改此行:

    #for entry in sorted(os.scandir(path), key=lambda e: int(os.path.splitext(e.name)[0])):
    for entry in sorted(listdir_nohidden(path), key=lambda e: int(os.path.splitext(e.name)[0])):  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-01
      • 2021-05-08
      • 1970-01-01
      • 2018-05-20
      相关资源
      最近更新 更多