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

4

我有一个目录,里面包含许多文件夹和文件。我想编写一个脚本,以查找目录中最新的文件的路径和名称,无论是在其子目录中还是在目录本身中。每当我想运行程序时,都会从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代码的可读性,但这段代码简短易懂。


使用os.walk - Peter Wood
2个回答

3

在嵌套的列表推导式中,使用os.walk(忽略目录)代替os.listdir并传递给sort

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)

正如某人所指出的,如果你只需要一个文件,你可以使用 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)需要您更改当前目录,除非

哈哈,我错过了脚本的第一行:"os.chdir( path )"。:p 但是谢谢,我会尝试一下并回复你! - SinByCos
2
你不需要对它们进行排序,你只是想要最新的。使用 max 即可。 - Peter Wood
@PeterWood 这是真的。幸运的是,max使用了key,所以只需要进行小的更改。 - Jean-François Fabre
我需要文件的路径。 - SinByCos
答案提供了完整路径的文件。 - Jean-François Fabre
是的。刚看到 :) - SinByCos

3

您可以编写一个通用的函数,使用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将每次比较调用以对文件进行排序。

首先是一个不错的设计模式。 - Jean-François Fabre
1
在Windows系统中要小心,一些过时的人可能会将文件命名为FOO.CPP(大写),这可能导致您的过滤器无法正常工作。 - Jean-François Fabre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接