29

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?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
BeeBand
  • 10,953
  • 19
  • 61
  • 83
  • 1
    Learn regex's special characters; dot `.` matches almost anything (line breaks optional). http://docs.python.org/library/re.html#regular-expression-syntax – Nick T Aug 31 '10 at 13:39
  • 1
    I think your regExp needs a slight modification, something like `code`if re.search('.*\.c$', f):`code` – Fairy Bower Nov 15 '12 at 02:41

15 Answers15

49

try changing the inner loop to something like this

results += [each for each in os.listdir(folder) if each.endswith('.c')]
deif
  • 1,349
  • 1
  • 14
  • 19
33

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,395
  • 1
  • 13
  • 17
  • 5
    +1: this is exactly what glob was designed for. Using regex is massive overkill. – Dave Kirby Aug 31 '10 at 12:53
  • @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 Aug 31 '10 at 15:53
  • `glob` also uses regex plus `os.listdir()` - plus many generators, function calls, recursion, if/else's, os.path.split + join ... So its slow, but simple usage, if you need the complete path anyway. Strange: on Windows internally posixmodule.c uses `FileFindFirstW/NextW("directory\\*.*")` for `os.listdir("directory")` :-) So consider `win32api.FindFiles('directory/*.c')]` on Windows for speed. – kxr Mar 01 '16 at 07:24
  • What if my files are in some other directory and I want just filenames and not file paths? It seems blob returns path. – Sulphur Apr 05 '22 at 23:36
7

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
  • 16,680
  • 9
  • 52
  • 65
6

There is a better solution that directly using regular expressions, it is the standard library's module fnmatch for dealing with file name patterns. (See also glob module.)

Write a helper function:

import fnmatch
import os

def listdir(dirname, pattern="*"):
    return fnmatch.filter(os.listdir(dirname), pattern)

and use it as follows:

result = listdir("./sources", "*.c")
firegurafiku
  • 3,017
  • 1
  • 28
  • 37
5
for _,_,filenames in os.walk(folder):
    for file in filenames:
        fileExt=os.path.splitext(file)[-1]
        if fileExt == '.c':
            results.append(file)
fredley
  • 32,953
  • 42
  • 145
  • 236
3

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
  • 16,773
  • 7
  • 36
  • 54
2

Change the directory to the given path, so that you can search files within directory. If you don't change the directory then this code will search files in your present directory location:

import os  #importing os library 
import glob #importing glob library

path=raw_input()  #input from the user 
os.chdir(path)

filedata=glob.glob('*.c') #all files with .c extenstions stores in filedata.
print filedata
DimaSan
  • 12,264
  • 11
  • 65
  • 75
banoth ravinder
  • 1,314
  • 15
  • 18
  • 2
    While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – DimaSan Mar 15 '17 at 11:23
  • @DimaSan Thanks for your suggestion. Now i edited the code. – banoth ravinder Mar 16 '17 at 10:25
2

Here's yet another solution, using pathlib (and Python 3):

from pathlib import Path

gamefolder = "path/to/dir"
result = sorted(Path(gamefolder).glob("**.c"))

Notice the double asterisk (**) in the glob() argument. This will search the gamefolder as well as its subdirectories. If you only want to search the gamefolder, use a single * in the pattern: "*.c". For more details, see the documentation.

natka_m
  • 1,297
  • 17
  • 22
1
import os, re
cfile = re.compile("^.*?\.c$")
results = []

for name in os.listdir(directory):
    if cfile.match(name):
        results.append(name)
Manoj Govindan
  • 72,339
  • 21
  • 134
  • 141
  • can you give an explanation for the regex `"^.*?\.c$"`. Would `'[.].c$` not be sufficient as @Vatine has suggested? – BeeBand Aug 31 '10 at 11:25
  • 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 Aug 31 '10 at 11:34
  • @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 Aug 31 '10 at 11:47
  • @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 Aug 31 '10 at 11:50
1

this is pretty clean. the commands come from the os library. this code will search through the current working directory and list only the specified file type. You can change this by replacing 'os.getcwd()' with your target directory and choose the file type by replacing '(ext)'. os.fsdecode is so you don't get a bytewise error from .endswith(). this also sorts alphabetically, you can remove sorted() for the raw list.

    import os
    filenames = sorted([os.fsdecode(file) for file in os.listdir(os.getcwd()) if os.fsdecode(file).endswith(".(ext)")])
  • Please be more specific on why this adds on to answers already present and more importantly, why it works. – GKE Jan 17 '19 at 23:55
  • The question is about `.c` files, not `.vtt`. – Beniamin H Jan 17 '19 at 23:56
  • Benjamin you can use it to find any extension. @GKE its one line, and it will list all of the files in the current working directory of a particular extension. – Will Morgan Jan 18 '19 at 00:39
1

The implementation of shutil.copytree is in the docs. I mofdified it to take a list of extentions to INCLUDE.

def my_copytree(src, dst, symlinks=False, *extentions):
    """ I modified the 2.7 implementation of shutils.copytree
    to take a list of extentions to INCLUDE, instead of an ignore list.
    """
    names = os.listdir(src)
    os.makedirs(dst)
    errors = []
    for name in names:
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        try:
            if symlinks and os.path.islink(srcname):
                linkto = os.readlink(srcname)
                os.symlink(linkto, dstname)
            elif os.path.isdir(srcname):
                my_copytree(srcname, dstname, symlinks, *extentions)
            else:
                ext = os.path.splitext(srcname)[1]
                if not ext in extentions:
                    # skip the file
                    continue
                copy2(srcname, dstname)
            # XXX What about devices, sockets etc.?
        except (IOError, os.error), why:
            errors.append((srcname, dstname, str(why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except Error, err:
            errors.extend(err.args[0])
    try:
        copystat(src, dst)
    # except WindowsError: # cant copy file access times on Windows
    #     pass
    except OSError, why:
        errors.extend((src, dst, str(why)))
    if errors:
        raise Error(errors)

Usage: For example, to copy only .config and .bat files....

my_copytree(source, targ, '.config', '.bat')

Mark Hall
  • 53,938
  • 9
  • 94
  • 111
Scott
  • 4,211
  • 3
  • 17
  • 20
0

Just to be clear, if you wanted the dot character in your search term, you could've escaped it too:

'.*[backslash].c' would give you what you needed, plus you would need to use something like:

results.append(f), instead of what you had listed as results += [f]

tjborromeo
  • 156
  • 6
0

This function returns a list of all file names with the specified extension that live in the specified directory:

import os

def listFiles(path, extension):
    return [f for f in os.listdir(path) if f.endswith(extension)]

print listFiles('/Path/to/directory/with/files', '.txt')

If you want to list all files with the specified extension in a certain directory and its subdirectories you could do:

import os

def filterFiles(path, extension):
    return [file for root, dirs, files in os.walk(path) for file in files if file.endswith(extension)]

print filterFiles('/Path/to/directory/with/files', '.txt')
heinst
  • 8,520
  • 7
  • 41
  • 77
0

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
  • 20,782
  • 4
  • 54
  • 70
0

You can actually do this with just os.listdir

import os
results = [f for f in os.listdir(gamefolders/folder) if f.endswith('.c')]