388

How do I count only the files in a directory? This counts the directory itself as a file:

len(glob.glob('*'))
1
  • 2
    To leave out directories, you can do '*.fileextension' for whatever file extension you are looking for. Commented Mar 24, 2018 at 2:28

29 Answers 29

429

os.listdir() will be slightly more efficient than using glob.glob. To test if a filename is an ordinary file (and not a directory or other entity), use os.path.isfile():

import os, os.path

# simple version for working with CWD
print len([name for name in os.listdir('.') if os.path.isfile(name)])

# path joining version for other paths
DIR = '/tmp'
print len([name for name in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, name))])
Sign up to request clarification or add additional context in comments.

11 Comments

Remember to add the folder_path inside os.path.filename(name) if you're not on the cwd. stackoverflow.com/questions/17893542/…
For recursively counting files nested inside directories, you might be better off with the os.walk() solution.
What is the benefit of using os.path.join(DIR, name) over DIR + '/' + name? The latter is shorter and, IMO, more clear than the former. Is there perhaps some OS:es on which the latter would fail?
@HelloGoodbye That's exactly the reason.
For those who uses python3, print(len(os.listdir('DIRECTORY_PATH')))
|
186
import os

_, _, files = next(os.walk("/usr/lib"))
file_count = len(files)

4 Comments

This isn't recursive
The OP didn't ask for it to be recursive
does os.walk no print it in sorted order?
Fails if folder is empty with StopIteration
89

For all kind of files, subdirectories included (Python 2):

import os

lst = os.listdir(directory) # your directory path
number_files = len(lst)
print number_files

Only files (avoiding subdirectories):

import os

onlyfiles = next(os.walk(directory))[2] #directory is your directory path as string
print len(onlyfiles)

4 Comments

This isn't recursive
The editing queue is full so... Please, do not use the builtins (list, dir) as a variable name or a placeholder!
@NickVeld FTFY...
Fails if folder is empty with StopIteration
53

This is where fnmatch comes very handy:

import fnmatch

print len(fnmatch.filter(os.listdir(dirpath), '*.txt'))

More details: http://docs.python.org/2/library/fnmatch.html

1 Comment

This is much faster (about half the time with my testing on a directory with 10,000 files) if you know the pattern you're looking for, rather then testing each file with os.path.isfile() as the accepted answer does. Also significantly faster than glob.glob().
36

An answer with pathlib and without loading the whole list to memory:

from pathlib import Path

path = Path('.')

print(sum(1 for _ in path.glob('*')))  # Files and folders, not recursive
print(sum(1 for _ in path.rglob('*')))  # Files and folders, recursive

print(sum(1 for x in path.glob('*') if x.is_file()))  # Only files, not recursive
print(sum(1 for x in path.rglob('*') if x.is_file()))  # Only files, recursive

5 Comments

Best answer by far!
or just sum(1 for _ in path.iterdir()) or sum(1 for _, x in enumerate(path.iterdir()) if x.is_file()). Not recursive.
Instead of path.glob('**/*') use path.rglob('*'), for recursive versions.
@MaximilianWolf Also an option, but it may have different behavior, so I used glob to have the same behavior for both recursive and non-recursive variants.
Sadly, "without loading the whole list to memory" is not the case. The implementation of all the pathlib components that scrape directories are eager in listing the actual directory, using os.listdir (they clearly intended to use os.scandir at one point, but found it caused problems with running out of file handles while recursively traversing deep directory trees, and fixed it by just making all processing eagerly slurp the whole directory so the handle gets closed immediately). So you avoid building a list of 1s or the like here, but the list of pathlib.Paths is always built.
35

If you want to count all files in the directory - including files in subdirectories, the most pythonic way is:

import os

file_count = sum(len(files) for _, _, files in os.walk(r'C:\Dropbox'))
print(file_count)

We use sum that is faster than explicitly adding the file counts (timings pending)

4 Comments

Hi, I was trying to understand this code (the code works perfect), I know we can use _ in a for loop. os.walk also I know. But not sure what's going on with underscores inside the sum function, could you please elaborate. Thanks!
Unsderscore is just a variable name @Ejaz, by convention used when we ignore the variable - that's what we do here - we call walk and only count the number of files in each directory, ignoring the root and dirs walk return values
This is completely recursive and probably the best answer here.
This should be the most appropriate answer, to also count the files in any subfolders..
25

Short and simple

import os
directory_path = '/home/xyz/'
No_of_files = len(os.listdir(directory_path))

3 Comments

Also, no need of directory path if the python file is in the same directory.
Importantly, this works well in Python 3
This solution counts also directories, not only files as it was indicated in question.
23

I am surprised that nobody mentioned os.scandir:

def count_files(dir):
    return sum(1 for x in os.scandir(dir) if x.is_file())

3 Comments

Works great with Python 3.6!
Why make lists, twice, for no benefit? sum(1 for entry in os.scandir(dir) if entry.is_file()) would achieve the same effect without producing two thoroughly unnecessary lists, and thereby keep memory usage constant regardless of directory size.
Note: I agree scandir is the way to go. It improves on listdir+os.path.isfile in two ways, 1) It's lazy and therefore works on huge directories efficiently (if you don't listify the result just to iterate it), and 2) The .is_file() call is satisfied from information the directory traversal API gives you for free, without a separate stat call, dramatically reducing the number of system calls and I/O required to complete the counting process.
13
def directory(path,extension):
  list_dir = []
  list_dir = os.listdir(path)
  count = 0
  for file in list_dir:
    if file.endswith(extension): # eg: '.txt'
      count += 1
  return count

Comments

12
import os
print len(os.listdir(os.getcwd()))

1 Comment

This might be useful sometimes but it includes subdirectories in the count also
10

This uses os.listdir and works for any directory:

import os
directory = 'mydirpath'

number_of_files = len([item for item in os.listdir(directory) if os.path.isfile(os.path.join(directory, item))])

this can be simplified with a generator and made a little bit faster with:

import os
isfile = os.path.isfile
join = os.path.join

directory = 'mydirpath'
number_of_files = sum(1 for item in os.listdir(directory) if isfile(join(directory, item)))

Comments

10

While I agree with the answer provided by @DanielStutzbach: os.listdir() will be slightly more efficient than using glob.glob.

However, an extra precision, if you do want to count the number of specific files in folder, you want to use len(glob.glob()). For instance if you were to count all the pdfs in a folder you want to use:

pdfCounter = len(glob.glob1(myPath,"*.pdf"))

Comments

7

This is an easy solution that counts the number of files in a directory containing sub-folders. It may come in handy:

import os
from pathlib import Path

def count_files(rootdir):
    '''counts the number of files in each subfolder in a directory'''
    for path in pathlib.Path(rootdir).iterdir():
        if path.is_dir():
            print("There are " + str(len([name for name in os.listdir(path) \
            if os.path.isfile(os.path.join(path, name))])) + " files in " + \
            str(path.name))
            
 
count_files(data_dir) # data_dir is the directory you want files counted.

You should get an output similar to this (with the placeholders changed, of course):

There are {number of files} files in {name of sub-folder1}
There are {number of files} files in {name of sub-folder2}

Comments

6
def count_em(valid_path):
   x = 0
   for root, dirs, files in os.walk(valid_path):
       for f in files:
            x = x+1
print "There are", x, "files in this directory."
return x

Taked from this post

1 Comment

1. files is a list. 2. OP is not looking for recursive count
6

one liner and recursive:

def count_files(path):
    return sum([len(files) for _, _, files in os.walk(path)])

count_files('path/to/dir')

Comments

5
import os

def count_files(in_directory):
    joiner= (in_directory + os.path.sep).__add__
    return sum(
        os.path.isfile(filename)
        for filename
        in map(joiner, os.listdir(in_directory))
    )

>>> count_files("/usr/lib")
1797
>>> len(os.listdir("/usr/lib"))
2049

Comments

5

Here is a simple one-line command that I found useful:

print int(os.popen("ls | wc -l").read())

1 Comment

Parsing the output of ls is generally frowned upon (it can frequently cause issues), though this is not a bad "quick-and-dirty" method at the shell. You should use ls -1, though, so it guarantees one line per file.
4

Luke's code reformat.

import os

print len(os.walk('/usr/lib').next()[2])

1 Comment

Gives me AttributeError: 'generator' object has no attribute 'next' in Python 3.11
2

I used glob.iglob for a directory structure similar to

data
└───train
│   └───subfolder1
│   |   │   file111.png
│   |   │   file112.png
│   |   │   ...
│   |
│   └───subfolder2
│       │   file121.png
│       │   file122.png
│       │   ...
└───test
    │   file221.png
    │   file222.png

Both of the following options return 4 (as expected, i.e. does not count the subfolders themselves)

  • len(list(glob.iglob("data/train/*/*.png", recursive=True)))
  • sum(1 for i in glob.iglob("data/train/*/*.png"))

Comments

2

It is simple:

print(len([iq for iq in os.scandir('PATH')]))

it simply counts number of files in directory , i have used list comprehension technique to iterate through specific directory returning all files in return . "len(returned list)" returns number of files.

2 Comments

Welcome to Stack Overflow. The quality of this answer can be improved by adding an explanation: How to Answer
Thankyou Elletlar , i have edited my answer , i will make sure to respond in more comprehensive manner :D
1

If you'll be using the standard shell of the operating system, you can get the result much faster rather than using pure pythonic way.

Example for Windows:

import os
import subprocess

def get_num_files(path):
    cmd = 'DIR \"%s\" /A-D /B /S | FIND /C /V ""' % path
    return int(subprocess.check_output(cmd, shell=True))

1 Comment

But it won't be as portable.
1

I found another answer which may be correct as accepted answer.

for root, dirs, files in os.walk(input_path):    
for name in files:
    if os.path.splitext(name)[1] == '.TXT' or os.path.splitext(name)[1] == '.txt':
        datafiles.append(os.path.join(root,name)) 


print len(files) 

Comments

1

A simple utility function I wrote that makes use of os.scandir() instead of os.listdir().

import os 

def count_files_in_dir(path: str) -> int:
    file_entries = [entry for entry in os.scandir(path) if entry.is_file()]

    return len(file_entries)

The main benefit is that, the need for os.path.is_file() is eliminated and replaced with os.DirEntry instance's is_file() which also removes the need for os.path.join(DIR, file_name) as shown in other answers.

Comments

1

Simpler one:

import os
number_of_files = len(os.listdir(directory))
print(number_of_files)

1 Comment

This solution counts also directories, not only files as it was indicated in question.
0
import os

total_con=os.listdir('<directory path>')

files=[]

for f_n in total_con:
   if os.path.isfile(f_n):
     files.append(f_n)


print len(files)

1 Comment

The OP asked for the number of files, this lists directories as well.
0

i did this and this returned the number of files in the folder(Attack_Data)...this works fine.

import os
def fcount(path):
    #Counts the number of files in a directory
    count = 0
    for f in os.listdir(path):
        if os.path.isfile(os.path.join(path, f)):
            count += 1

    return count
path = r"C:\Users\EE EKORO\Desktop\Attack_Data" #Read files in folder
print (fcount(path))

Comments

0

I find that sometimes I don't know if I will receive filenames or the path to the file. So I printed the os walk solution output:

def count_number_of_raw_data_point_files(path: Union[str, Path], with_file_prefix: str) -> int:
    import os
    path: Path = force_expanduser(path)

    _, _, files = next(os.walk(path))
    # file_count = len(files)
    filename: str
    count: int = 0
    for filename in files:
        print(f'-->{filename=}')  # e.g. print -->filename='data_point_99.json'
        if with_file_prefix in filename:
            count += 1
    return count

out:

-->filename='data_point_780.json'
-->filename='data_point_781.json'
-->filename='data_point_782.json'
-->filename='data_point_783.json'
-->filename='data_point_784.json'
-->filename='data_point_785.json'
-->filename='data_point_786.json'
-->filename='data_point_787.json'
-->filename='data_point_788.json'
-->filename='data_point_789.json'
-->filename='data_point_79.json'
-->filename='data_point_790.json'
-->filename='data_point_791.json'
-->filename='data_point_792.json'
-->filename='data_point_793.json'
-->filename='data_point_794.json'
-->filename='data_point_795.json'
-->filename='data_point_796.json'
-->filename='data_point_797.json'
-->filename='data_point_798.json'
-->filename='data_point_799.json'
-->filename='data_point_8.json'
-->filename='data_point_80.json'
-->filename='data_point_800.json'
-->filename='data_point_801.json'
-->filename='data_point_802.json'
-->filename='data_point_803.json'
-->filename='data_point_804.json'
-->filename='data_point_805.json'
-->filename='data_point_806.json'
-->filename='data_point_807.json'
-->filename='data_point_808.json'
-->filename='data_point_809.json'
-->filename='data_point_81.json'
-->filename='data_point_810.json'
-->filename='data_point_811.json'
-->filename='data_point_812.json'
-->filename='data_point_813.json'
-->filename='data_point_814.json'
-->filename='data_point_815.json'
-->filename='data_point_816.json'
-->filename='data_point_817.json'
-->filename='data_point_818.json'
-->filename='data_point_819.json'
-->filename='data_point_82.json'
-->filename='data_point_820.json'
-->filename='data_point_821.json'
-->filename='data_point_822.json'
-->filename='data_point_823.json'
-->filename='data_point_824.json'
-->filename='data_point_825.json'
-->filename='data_point_826.json'
-->filename='data_point_827.json'
-->filename='data_point_828.json'
-->filename='data_point_829.json'
-->filename='data_point_83.json'
-->filename='data_point_830.json'
-->filename='data_point_831.json'
-->filename='data_point_832.json'
-->filename='data_point_833.json'
-->filename='data_point_834.json'
-->filename='data_point_835.json'
-->filename='data_point_836.json'
-->filename='data_point_837.json'
-->filename='data_point_838.json'
-->filename='data_point_839.json'
-->filename='data_point_84.json'
-->filename='data_point_840.json'
-->filename='data_point_841.json'
-->filename='data_point_842.json'
-->filename='data_point_843.json'
-->filename='data_point_844.json'
-->filename='data_point_845.json'
-->filename='data_point_846.json'
-->filename='data_point_847.json'
-->filename='data_point_848.json'
-->filename='data_point_849.json'
-->filename='data_point_85.json'
-->filename='data_point_850.json'
-->filename='data_point_851.json'
-->filename='data_point_852.json'
-->filename='data_point_853.json'
-->filename='data_point_86.json'
-->filename='data_point_87.json'
-->filename='data_point_88.json'
-->filename='data_point_89.json'
-->filename='data_point_9.json'
-->filename='data_point_90.json'
-->filename='data_point_91.json'
-->filename='data_point_92.json'
-->filename='data_point_93.json'
-->filename='data_point_94.json'
-->filename='data_point_95.json'
-->filename='data_point_96.json'
-->filename='data_point_97.json'
-->filename='data_point_98.json'
-->filename='data_point_99.json'
854

note you might have to sort.

Comments

0

I would like to extend the reply from @Mr_and_Mrs_D:

import os
folder = 'C:/Dropbox'
file_count = sum(len(files) for _, _, files in os.walk(folder))
print(file_count)

This counts all the files in the folder and its subfolders. However, if you want to do some filtering - like only counting the files ending in .svg, you can do:

import os
file_count = sum(len([f for f in files if f.endswith('.svg')]) for _, _, files in os.walk(folder))
print(file_count)

You basically replace:

  • len(files)

with:

  • len([f for f in files if f.endswith('.svg')])

Comments

-2

Convert it to a list, after that you can make use of the len() function:

len(list(glob.glob('*')))

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.