I have a directory in which I have many folders, AS WELL as files. I want to write a script that finds the path and name of the most recent file that exists in the directory, either in one of its sub-directories, or in the directory itself. This will be run from VSCode whenever I want to run a program. Earlier I had something like this. It worked ONLY for files in the directory, and not files in sub-directories.
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"]
)
Here's the output of "ls -ltr" in Terminal. The last three lines are for folders.
-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
Maybe in the future, I might have sub-directories INSIDE my sub-directories, so if any suggested script can work in that scenario as well, it would be even more appreciated.
EDIT
I liked both the answers, by Peter and Jean, so thanks! My file now:
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]
)
It's short and simple, though I also liked the readability of Peter's code.
Use os.walk, (ignoring directories), instead of os.listdir in a nested list comprehension fed to 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)
As someone noted, if you only need 1 file, you can just apply max with a key (and in that case, switch to generator comprehension, since you don't need the full list to feed to sort and optimize speed):
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)
note that your expression files = sorted(os.listdir(path), key=os.path.getctime, reverse = True) needs you to change current directory unless path is not the current path, because listdir returns the file names not the file paths (and yes, you also have to filter out directories, which complexifies the expression further. You don't have this problem anymore with the solution above since os.path.join is applied before sorting)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With