【问题标题】:Finding the newest files in multiple folders and send them to other folder在多个文件夹中查找最新文件并将它们发送到其他文件夹
【发布时间】:2020-09-05 17:10:48
【问题描述】:

我在 Source 中有 3 个文件夹(A、B 和 C)。每个文件夹至少包含 1 个文件。我想在每个文件夹中找到最新的文件并将其发送到还包含文件夹 A、B 和 C 的目标。不是最新的文件将被移动到存档,其中还包含文件夹 A、B 和 C。我使用了下面的代码,但我收到以下错误:NotADirectoryError: [WinError 267] The directory name is invalid: 'c:\\data\\AS\\Desktop\\Source\\A\\12.txt'

这是我的代码:

from datetime import datetime,timedelta
import shutil, os, os.path
import time

#Make Source, Destination and Archive paths.
source = r'c:\data\AS\Desktop\Source'
destination = r'c:\data\AS\Desktop\Destination'
archive = r'c:\data\AS\Desktop\Archive'

#First os.walk for the source folder itself
for root, dirs, files in os.walk(source):
    for folder in dirs:
        subdir=root+'\\'+folder
        #second os.walk for each folder in the source folder (A, B, and C)
        for subroot, subdirs, subfiles in os.walk(subdir):
            for file in subfiles:
                filePath=subroot+'\\'+file
                maxi = max(os.listdir(filePath), key=os.path.getctime)
                print(maxi)

我也想知道 key=os.path.getctime 中的 key 代表什么。先谢谢大家了

【问题讨论】:

    标签: python file file-management


    【解决方案1】:

    如果您的目标只是将子目录中的文件移动到比source 低一级,那么您不想使用os.walk()。这是一个递归遍历,将枚举根目录下的所有目录/文件。相反,使用os.listdir(),它只会列出直接的子目录和文件。另请注意,os.path.getctime() 需要完整的路径,并且仅在os.listdir() 返回的文件名下不起作用。

    import os
    import os.path
    
    src = 'src'
    dst = 'dst'
    arc = 'arc'
    
    for subdir in os.listdir(src):
        subdir_path = os.path.join(src, subdir)
        if not os.path.isdir(subdir_path):
            # Only consider directories (a, b, c, ...) under src; skip files.
            continue
    
        # Get a list of absolute paths of _files_ in the sub-directory.
        subfile_paths = [os.path.join(subdir_path, f) for f in os.listdir(subdir_path)]
        subfile_paths = [p for p in subfile_paths if os.path.isfile(p)]
    
        if len(subfile_paths) == 0:
            # Skip empty sub-directories.
            continue
    
        newest_path = max(subfile_paths, key=os.path.getctime)
    
        for subfile_path in subfile_paths:
            if subfile_path == newest_path:
                dst_root = dst
            else:
                dst_root = arc
    
            dst_path = os.path.join(dst_root, subdir, os.path.basename(subfile_path))
            os.rename(subfile_path, dst_path)
    
    

    【讨论】:

    • 现在您的代码实际上完全符合我的要求,谢谢。但是你能帮我看看吗?例如,两个 subfile_paths 之间有什么区别?我还有另一个快速的。现在只有 MAX 文件被移动到目的地,比如如果我想添加和其他要求它们必须是 MAX 文件并且它们必须至少有 120 秒的历史。我想添加一个 os.stat(subfile_paths) 和 current.time 并使用 >60 / 2?提前谢谢!
    • 第一个subfile_paths 列表解析是通过应用os.path.joinsubdir 中的文件列表转换为绝对路径。第二个是过滤掉任何不是常规文件的路径(例如,src/a/ 中可能有一个目录),只保留os.path.isfile(p) == True 中的那些路径。您可以通过对os.path.join 的冗余调用或仅使用普通的for 循环在一个列表理解中执行此操作。
    • 如果您只想将最新的并且至少 120 秒的文件移动到 dst,您可以添加另一个条件:if subfile_path == newest_path and os.path.getctime(newest_path) < time.time() - 120:
    • 谢谢。那效果很好。看到您甚至无需使用 shutil.move 就可以移动文件,这很“奇怪”。你怎么不用那个?比如实际“移动”文件的代码在哪里?
    • shutil.move 实际上会调用os.rename,除非目标位于不同的文件系统上。如果有可能,您应该改用shutil.move。在同一个文件系统中,不需要实际移动文件数据。
    【解决方案2】:

    你得到的错误是这一行的结果:

    maxi = max(os.listdir(filePath), key=os.path.getctime)
    

    您不需要为文件夹 A、B 和 C 执行第二个 os.walk 函数。执行此操作时,您将完整的文件路径分配给变量 filePath。然后,当您将 filePath 传递给 max() 函数时,它会引发您看到的错误,因为它需要一个文件夹。您应该将 A、B 和 C 文件夹的路径传递给 max() 函数,而不是单个文件的路径。您应该能够摆脱第二个 os.walk 结构。像这样的:

    for root, dirs, files in os.walk(source):
    for folder in dirs:
        subdir=root+'\\'+folder
        maxi = max(os.listdir(subdir), key=os.path.getctime)
        print(maxi)
    

    另外,key=os.path.getctime 告诉 max() 函数使用文件创建的时间戳来确定最大值。所以你是说向我展示最大文件,其中最大定义为最近创建的时间。

    【讨论】:

    • 这是否意味着 key 是 Python 已知的关键字?因为当我更改密钥时会出现错误。
    • 是的,它是 max() 函数的可选参数 - see this
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多