如何从 Python 目录的所有子目录中找到最近修改的文件?

How to find most recently modified file from all subdirectories in a directory in Python?

我有一个目录,其中有很多文件夹和文件。我想编写一个脚本来查找目录中存在的最新文件的路径和名称,无论是在其子目录之一中,还是在目录本身中。每当我想 运行 一个程序时,这将是 VSCode 的 运行。早些时候我有这样的事情。它只对目录中的文件有效,对子目录中的文件无效。

files = sorted(os.listdir(path), key=os.path.getctime, reverse = True)
for file in files: #Finds most recent file with '.cpp' extension
    if ".cpp" in file:
        last = file
        break
subprocess.call(
    ["g++", "-std=c++14", path + last]
    )
subprocess.call(
    ["open", path + "./a.out"]
)

这是终端中 "ls -ltr" 的输出。最后三行用于文件夹。

-rw-r--r--@  1 tanavya.dimri  staff     2182 Mar 23 16:10 UVa_LEDTest.cpp
-rw-r--r--@  1 tanavya.dimri  staff     4217 Mar 23 16:11 OPC_SiruseriMetro.cpp
-rw-r--r--@  1 tanavya.dimri  staff     2645 Mar 23 16:12 UVa_Password.cpp
-rw-r--r--@  1 tanavya.dimri  staff      940 Mar 23 16:13 UVa_8Queens.cpp
-rw-r--r--@  1 tanavya.dimri  staff     1587 Mar 23 20:57 UVa12405_Scarecrow.cpp
-rw-r--r--@  1 tanavya.dimri  staff     3014 Mar 25 19:58 UVa_Zones.cpp
-rw-r--r--@  1 tanavya.dimri  staff     2733 Mar 25 20:07 YogesMM.cpp
-rw-r--r--@  1 tanavya.dimri  staff     1066 Mar 26 22:33 ChefAndTraingles.cpp
-rw-r--r--@  1 tanavya.dimri  staff      993 Mar 27 07:10 untitled.cpp
-rw-r--r--   1 tanavya.dimri  staff       33 Mar 27 21:42 out.out
-rwxr-xr-x   1 tanavya.dimri  staff    15564 Mar 27 22:54 a.out
drwxr-xr-x   8 tanavya.dimri  staff      272 Mar 27 23:35 SpecificAlgorithms
drwxr-xr-x  25 tanavya.dimri  staff      850 Mar 30 12:49 DynamicProgramming
drwxr-xr-x   5 tanavya.dimri  staff      170 Mar 30 16:27 GraphTheory

也许在未来,我的子目录中可能会有子目录,所以如果任何建议的脚本也可以在这种情况下工作,我们将不胜感激。

编辑

我喜欢 Peter 和 Jean 的两个答案,非常感谢! 我现在的档案:

import os
import subprocess

path = "/Users/tanavya.dimri/Desktop/CompetitiveProgramming/"

most_recent_file = max((os.path.join(root,f) for root,_,the_files in os.walk(path) for f in the_files if f.lower().endswith(".cpp")),key=os.path.getctime)
subprocess.call(
                ["g++", "-std=c++14", most_recent_file]
                )
run_file = max((os.path.join(root,f) for root,_,the_files in os.walk(path) for f in the_files if f.lower() == "a.out"),key=os.path.getctime)
subprocess.call(
                ["open", run_file]
                )

虽然我也喜欢 Peter 代码的可读性,但它又短又简单。

在提供给 sort

的嵌套列表理解中使用 os.walk,(忽略目录),而不是 os.listdir
files = sorted([os.path.join(root,f) for root,_,the_files in os.walk(path) for f in the_files if f.lower().endswith(".cpp")], key=os.path.getctime, reverse = True)

正如有人指出的那样,如果您只需要 1 个文件,则只需将 maxkey 一起应用(在这种情况下,切换到生成器理解,因为您不需要完整列表以提供给 sort 并优化速度):

most_recent_file = max((os.path.join(root,f) for root,_,the_files in os.walk(path) for f in the_files if f.lower().endswith(".cpp")),key=os.path.getctime)

请注意,您的表达式 files = sorted(os.listdir(path), key=os.path.getctime, reverse = True) 需要您更改当前目录,除非 path 不是当前路径,因为 listdir returns 是文件名而不是文件路径(是的,您还必须过滤掉目录,这会使表达式进一步复杂化。由于在排序之前应用了 os.path.join,因此使用上述解决方案不再有此问题)

您可以使用 os.walk:

编写一个普遍有用的函数来生成目录中和目录下的所有文件路径
def filepaths(directory):
    for root, dirs, filenames in os.walk(directory):
        for filename in filenames:
            yield os.path.join(root, filename)

然后你可以编写一个生成器来过滤掉 .cpp 个文件,确保比较时不考虑大小写,首先将路径转换为小写:

cpps = (filepath for filepath in filepaths(directory)
        if filepath.lower().endswith('.cpp'))

您可以在密钥为 os.path.getctime 的文件上使用 max:

latest = max(cpps, key=os.path.getctime)

使用 max 的一个优点是 os.path.getctime 只为每个文件路径调用一次。您使用 sorted 的解决方案效率低下,因为您实际上并不需要按顺序排列所有修改时间,您只需要最新的。 getctime 将在每次比较时调用以使文件有序。