tags:

views:

131

answers:

7

I am trying to find all the .c files in a directory using Python.

I wrote this, but it is just returning me all files - not just .c files.

import os
import re

results = []

for folder in gamefolders:
    for f in os.listdir(folder):
        if re.search('.c', f):
            results += [f]

print results

How can I just get the .c files?

+3  A: 
for _,_,filenames in os.walk(folder):
    for file in filenames:
        fileExt=os.path.splitext(file)[-1]
        if fileExt == '.c':
            results.append(file)
fredley
@fredley, I wanted to avoid `os.walk` as it seems to be quite slow.
BeeBand
@BeeBand Fair enough
fredley
@fredley - This code runs for about 3 minutes and then returns me an empty list. Just wondering if you tried it out?
BeeBand
It should be "if fileExt == '.c':" - the dot is included in the extension part. See http://docs.python.org/library/os.path.html#os.path.splitext
Pieter Witvoet
@Pieter ammended
fredley
+7  A: 

Try "glob":

>>> import glob
>>> glob.glob('./[0-9].*')
['./1.gif', './2.txt']
>>> glob.glob('*.gif')
['1.gif', 'card.gif']
>>> glob.glob('?.gif')
['1.gif']
Maciej Kucharz
+1: this is exactly what glob was designed for. Using regex is massive overkill.
Dave Kirby
@Dave - some people seem to think that `glob` is somewhat overkill also ( see @Jive's comment below ). I don't know enough about the internals of `glob` to comment on that.
BeeBand
+1  A: 
import os, re
cfile = re.compile("^.*?\.c$")
results = []

for name in os.listdir(directory):
    if cfile.match(name):
        results.append(name)
Manoj Govindan
@Manoj, can you give an explanation for the regex `"^.*?\.c$"`. Would `'[.].c$` not be sufficient as @Vatine has suggested?
BeeBand
@Manoj, I ran your code and it returns me and empty list - have you tried this out on a bunch of .c files? Perhaps it's something to do with the names of my files. @Vatine's code works however.
BeeBand
@BeeBand: (response to second comment): I *did* test it; I am getting all `.c` files in a given `directory`. Are your file extensions upper case by any chance? In that case you will need to use the `re.I` flag when compiling the regular expression.
Manoj Govindan
@BeeBand: (response to first comment): `'[.].c$` would indeed be sufficient. I merely re-used an expression from a script I had written for a different file type.
Manoj Govindan
A: 

If you replace '.c' with '[.]c$', you're searching for files that contain .c as the last two characters of the name, rather than all files that contain a c, with at least one character before it.

Edit: Alternatively, match f[-2:] with '.c', this MAY be computationally cheaper than pulling out a regexp match.

Vatine
@Vatine, great - that works.
BeeBand
Using re or glob wins the Sledge-Hammer-to-Kill-a-Fly Award.
Jive Dadson
+6  A: 

try changing the inner loop to something like this

results += [each for each in os.listdir(folder) if each.endswith('.c')]
deif
@deif, that works - but for clarity it should be `results += [each for each in os.listdir(folder) if each.endswith(`.c`)].
BeeBand
@BeeBand right, thanks. i missed your question update, now my answer is updated as well.
deif
@deif, I like the one liner, so this one gets the points.
BeeBand
+1  A: 

KISS

# KISS

import os

results = []

for folder in gamefolders:
    for f in os.listdir(folder):
        if f.endswith('.c'):
            results.append(f)

print results
Jive Dadson
+2  A: 

For another alternative you could use fnmatch

import fnmatch
import os

results = []
for root, dirs, files in os.walk(path)
    for _file in files:
        if fnmatch.fnmatch(_file, '*.c'):
            results.append(os.path.join(root, _file))

print results

or with a list comprehension:

for root, dirs, files in os.walk(path)
    [results.append(os.path.join(root, _file))\
        for _file in files if \
            fnmatch.fnmatch(_file, '*.c')] 

or using filter:

for root, dirs, files in os.walk(path):
    [results.append(os.path.join(root, _file))\
        for _file in fnmatch.filter(files, '*.c')]     
volting