The intent of this script is to hunt down all "*/testResults/*.xml"
files and touch them, so that our build system doesn't issue errors that the files are too old (it's entirely intentional that tests are only re-run when the libraries they change have been modified)
import fnmatch
import os
import time
matches = []
# Find all xml files (1)
for root, dirnames, filenames in os.walk('.'):
for filename in fnmatch.filter(filenames, '*.xml'):
matches.append(os.path.join(root, filename))
# filter to only the ones in a "/testResults/" folder (2)
tests = [k for k in matches if "\\testResults\\" in k]
t = time.time()
# touch them
for test in tests:
os.utime(test,(t,t))
Is there a simpler way to achieve this? Specifically to perform steps (1) and (2) in a single process, rather than having to filter the matches array? An alternative solution would be to just recursively find all folders called "/testResults/" and list the files within them.
Notes:
This script would also find "blah/testResults/blah2/result.xml" - I'm not worried about that, as the testResults folders will only contain test result xml files (but not all xml files are test results!)
This runs on Windows.
-
\$\begingroup\$ I don't think recursion is a good solution for this problem at all. You're initial solution is better. \$\endgroup\$James Khoury– James Khoury2014年01月30日 01:22:01 +00:00Commented Jan 30, 2014 at 1:22
-
\$\begingroup\$ I meant recursively in a filesystem sense (i.e. it could be /a/testResults/ or /a/b/testResults/ etc), not in a recursive function sense. \$\endgroup\$benjymous– benjymous2014年01月30日 09:13:41 +00:00Commented Jan 30, 2014 at 9:13
3 Answers 3
For combining (1) and (2) you can reverse the sort by only trying if your are under a test directory
Also this is a great use for a generator / map combo to avoid extra loops
import os
import re
is_xml = re.compile('xml', re.I)
is_test = re.compile('testResults', re.I)
def find_xml_tests(root):
for current, dirnames, filenames in os.walk(root):
if is_test.search(current):
for filename in filter(lambda p: is_xml.search(p), filenames):
yield os.path.normpath(os.path.join(current, filename))
def touch(filename ):
os.utime(test,(time.time(),time.time()))
map(touch, find_xml_tests('path/to/files'))
Python seems like overkill here: this is surely a job for the shell? Depending on exactly which files you want to touch, then use this:
touch -- */testResults/*.xml
or this:
find . -path '*/testResults/*.xml' -exec touch -- {} \+
You indicated that you are using Windows. But even on Windows, surely a PowerShell script (using Get-ChildItem
instead of find
and Set-ItemProperty -Name LastWriteTime
instead of touch
) would be simplest?
-
\$\begingroup\$ Yes, Windows I'm afraid! \$\endgroup\$benjymous– benjymous2014年01月29日 16:06:18 +00:00Commented Jan 29, 2014 at 16:06
-
1\$\begingroup\$ I've updated your question accordingly. \$\endgroup\$Gareth Rees– Gareth Rees2014年01月29日 16:08:03 +00:00Commented Jan 29, 2014 at 16:08
import os,glob,time
t = time.time()
def touchy(fpath):
os.utime(fpath,(t,t))
return fpath
def findResults(directory = "/"):
results = []
search_path = os.path.join(directory,"testResults/*.xml")
for d in filter(os.path.isdir,os.listdir(directory)):
results.extend( map(touchy,glob.glob(search_path)) if d == "testResults" else findResults(os.path.join(directory,d))
return results
is probably about the best you can do if you want python
-
\$\begingroup\$ Can you revise this to avoid the long line? \$\endgroup\$Gareth Rees– Gareth Rees2014年01月29日 18:09:30 +00:00Commented Jan 29, 2014 at 18:09
-
\$\begingroup\$ there its shorter lines ... still probably not quite pep-8 \$\endgroup\$Joran Beasley– Joran Beasley2014年01月29日 18:12:46 +00:00Commented Jan 29, 2014 at 18:12
Explore related questions
See similar questions with these tags.