How do I get a list of all files (and directories) in a given directory in Python?
-
2recursively or not? Clarify please. For non recursive solution see: https://stackoverflow.com/questions/973473/getting-a-list-of-all-subdirectories-in-the-current-directory – Charlie Parker Jul 20 '20 at 16:33
21 Answers
This is a way to traverse every file and directory in a directory tree:
import os
for dirname, dirnames, filenames in os.walk('.'):
# print path to all subdirectories first.
for subdirname in dirnames:
print(os.path.join(dirname, subdirname))
# print path to all filenames.
for filename in filenames:
print(os.path.join(dirname, filename))
# Advanced usage:
# editing the 'dirnames' list will stop os.walk() from recursing into there.
if '.git' in dirnames:
# don't go into any .git directories.
dirnames.remove('.git')
-
19And if you run this code (as is) from the Python Shell, recall that Ctrl+C will halt output to said shell. ;) – gary Dec 13 '11 at 17:56
-
41
-
You can even edit the dirnames list to prevent it from recursing down some paths. – bugloaf Oct 12 '12 at 20:11
-
9@Clément "When topdown is True, the caller can modify the dirnames list in-place (perhaps using del or slice assignment), and walk() will only recurse into the subdirectories whose names remain in dirnames; this can be used to prune the search, impose a specific order of visiting, or even to inform walk() about directories the caller creates or renames before it resumes walk() again." from http://docs.python.org/2/library/os.html#os.walk – bugloaf Feb 13 '13 at 18:08
-
The simpler way to ignore some directories is to not add them to dirnames in the first place `for subdirname in dirnames: if subdirname != '.git'` – smci May 22 '18 at 14:05
-
1@smci You've misunderstood. You've given a code snippet for not printing out the name of the .git directory. Removing it from dirnames causes the code to not recurse into the .git subdirectory. – Jerub Aug 08 '18 at 12:58
-
Oh I see, you intended to print every dirname, then recurse into every dirname except .git – smci Aug 08 '18 at 16:11
You can use
os.listdir(path)
For reference and more os functions look here:
- Python 2 docs: https://docs.python.org/2/library/os.html#os.listdir
- Python 3 docs: https://docs.python.org/3/library/os.html#os.listdir
-
2well the original question is just vague enough to not know whether they wanted a recursive solution. "all files in a directory" could be interpreted as recursive. – Tommy Dec 10 '15 at 02:01
-
3@Tommy, a “directory” is a clearly defined data structure, and it refers to "ls" rather than "ls -R". Besides, almost all UNIX tools don't work recursively by default. I don't know what the questioner *meant* but what he *wrote* was clear. – Torsten Bronger Jul 06 '16 at 13:19
-
3The python 3 docs tell you to use `os.scandir` instead however, since in many cases it allows you to prevent system calls, giving a free speedup (both IPC and IO are slow). – Jappie Kerk Apr 14 '17 at 09:54
-
10listdir gives you the only the filename in the directory, is there a method available to get full path? – greperror Aug 03 '17 at 21:04
-
1@greperror You can use [*os.path.abspath*](https://docs.python.org/2/library/os.path.html#os.path.abspath) for getting the full path. Also, to check if a given path is a file, use the [os.path.isfile](https://docs.python.org/2/library/os.path.html#os.path.isfile) or `os.path.isdir`. – Aleksandar Apr 01 '18 at 22:10
Here's a helper function I use quite often:
import os
def listdir_fullpath(d):
return [os.path.join(d, f) for f in os.listdir(d)]

- 1,995
- 1
- 11
- 5
-
6
-
3@RobertSiemer that depends on the usage. In many cases, a list would be better, but I guess a generator is more versatile since it can be converted to a list. It depends on whether you're looking for, versatility or something a little bit more streamlined. – James Mchugh Aug 09 '18 at 20:02
-
4It's been ten years, but I think I did it this way because os.listdir() returns a list and I was imitating that. – giltay Aug 14 '18 at 13:53
import os
for filename in os.listdir("C:\\temp"):
print filename

- 19,950
- 4
- 55
- 71
-
18`r'C:\temp'` is clearer and preferred to `"C:\\temp"` Rawstrings are preferable to escpaing backslashes. – smci Aug 26 '12 at 02:07
-
1
-
@martineau: there is no consensus; this is like emacs-vs-vi. Forward-slash is preferable because it can't be misinterpreted as escaping chars, but backward-slash is still more popular... – smci Mar 24 '21 at 22:14
-
1@smci: Forward slash is also portable and doesn't require a special prefix. I wouldn't criticize anyone for doing it the way the OP did. Anyhow, as far as popularity goes, we must move in different circles. `;¬)` – martineau Mar 24 '21 at 22:25
If you need globbing abilities, there's a module for that as well. For example:
import glob
glob.glob('./[0-9].*')
will return something like:
['./1.gif', './2.txt']
See the documentation here.

- 3,439
- 3
- 26
- 31
-
that's really awesome! can you have negation in those matching expression? like everything except files matching `THIS` pattern? – Charlie Parker Jul 20 '20 at 16:02
-
@CharlieParker: You can't do it directly with `glob`, but you can fairly easily with it or `os.listdir()` in conjunction with the `re` regular expression module — see [this answer](https://stackoverflow.com/a/13032338/355230) to another question. – martineau Mar 24 '21 at 10:58
For files in current working directory without specifying a path
Python 2.7:
import os
os.listdir('.')
Python 3.x:
import os
os.listdir()

- 12,464
- 7
- 65
- 73

- 386
- 1
- 3
- 12
Try this:
import os
for top, dirs, files in os.walk('./'):
for nm in files:
print os.path.join(top, nm)

- 854,327
- 234
- 1,573
- 1,953
-
In one line: [top + os.sep + f for top, dirs, files in os.walk('./') for f in files] – J. Peterson Apr 23 '13 at 21:10
While os.listdir()
is fine for generating a list of file and dir names, frequently you want to do more once you have those names - and in Python3, pathlib makes those other chores simple. Let's take a look and see if you like it as much as I do.
To list dir contents, construct a Path object and grab the iterator:
In [16]: Path('/etc').iterdir()
Out[16]: <generator object Path.iterdir at 0x110853fc0>
If we want just a list of names of things:
In [17]: [x.name for x in Path('/etc').iterdir()]
Out[17]:
['emond.d',
'ntp-restrict.conf',
'periodic',
If you want just the dirs:
In [18]: [x.name for x in Path('/etc').iterdir() if x.is_dir()]
Out[18]:
['emond.d',
'periodic',
'mach_init.d',
If you want the names of all conf files in that tree:
In [20]: [x.name for x in Path('/etc').glob('**/*.conf')]
Out[20]:
['ntp-restrict.conf',
'dnsextd.conf',
'syslog.conf',
If you want a list of conf files in the tree >= 1K:
In [23]: [x.name for x in Path('/etc').glob('**/*.conf') if x.stat().st_size > 1024]
Out[23]:
['dnsextd.conf',
'pf.conf',
'autofs.conf',
Resolving relative paths become easy:
In [32]: Path('../Operational Metrics.md').resolve()
Out[32]: PosixPath('/Users/starver/code/xxxx/Operational Metrics.md')
Navigating with a Path is pretty clear (although unexpected):
In [10]: p = Path('.')
In [11]: core = p / 'web' / 'core'
In [13]: [x for x in core.iterdir() if x.is_file()]
Out[13]:
[PosixPath('web/core/metrics.py'),
PosixPath('web/core/services.py'),
PosixPath('web/core/querysets.py'),

- 3,030
- 2
- 25
- 33
A recursive implementation
import os
def scan_dir(dir):
for name in os.listdir(dir):
path = os.path.join(dir, name)
if os.path.isfile(path):
print path
else:
scan_dir(path)

- 1,100
- 14
- 14
Here is another option.
os.scandir(path='.')
It returns an iterator of os.DirEntry objects corresponding to the entries (along with file attribute information) in the directory given by path.
Example:
with os.scandir(path) as it:
for entry in it:
if not entry.name.startswith('.'):
print(entry.name)
Using scandir() instead of listdir() can significantly increase the performance of code that also needs file type or file attribute information, because os.DirEntry objects expose this information if the operating system provides it when scanning a directory. All os.DirEntry methods may perform a system call, but is_dir() and is_file() usually only require a system call for symbolic links; os.DirEntry.stat() always requires a system call on Unix but only requires one for symbolic links on Windows.

- 3,774
- 1
- 27
- 36
I wrote a long version, with all the options I might need: http://sam.nipl.net/code/python/find.py
I guess it will fit here too:
#!/usr/bin/env python
import os
import sys
def ls(dir, hidden=False, relative=True):
nodes = []
for nm in os.listdir(dir):
if not hidden and nm.startswith('.'):
continue
if not relative:
nm = os.path.join(dir, nm)
nodes.append(nm)
nodes.sort()
return nodes
def find(root, files=True, dirs=False, hidden=False, relative=True, topdown=True):
root = os.path.join(root, '') # add slash if not there
for parent, ldirs, lfiles in os.walk(root, topdown=topdown):
if relative:
parent = parent[len(root):]
if dirs and parent:
yield os.path.join(parent, '')
if not hidden:
lfiles = [nm for nm in lfiles if not nm.startswith('.')]
ldirs[:] = [nm for nm in ldirs if not nm.startswith('.')] # in place
if files:
lfiles.sort()
for nm in lfiles:
nm = os.path.join(parent, nm)
yield nm
def test(root):
print "* directory listing, with hidden files:"
print ls(root, hidden=True)
print
print "* recursive listing, with dirs, but no hidden files:"
for f in find(root, dirs=True):
print f
print
if __name__ == "__main__":
test(*sys.argv[1:])

- 7,819
- 3
- 38
- 38
The one worked with me is kind of a modified version from Saleh's answer elsewhere on this page.
The code is as follows:
dir = 'given_directory_name'
filenames = [os.path.abspath(os.path.join(dir,i)) for i in os.listdir(dir)]

- 175,061
- 34
- 275
- 318

- 1,859
- 1
- 19
- 18
A nice one liner to list only the files recursively. I used this in my setup.py package_data directive:
import os
[os.path.join(x[0],y) for x in os.walk('<some_directory>') for y in x[2]]
I know it's not the answer to the question, but may come in handy

- 1,277
- 7
- 11
For Python 2
#!/bin/python2
import os
def scan_dir(path):
print map(os.path.abspath, os.listdir(pwd))
For Python 3
For filter and map, you need wrap them with list()
#!/bin/python3
import os
def scan_dir(path):
print(list(map(os.path.abspath, os.listdir(pwd))))
The recommendation now is that you replace your usage of map and filter with generators expressions or list comprehensions:
#!/bin/python
import os
def scan_dir(path):
print([os.path.abspath(f) for f in os.listdir(path)])

- 1,295
- 2
- 20
- 24
Below code will list directories and the files within the dir
def print_directory_contents(sPath):
import os
for sChild in os.listdir(sPath):
sChildPath = os.path.join(sPath,sChild)
if os.path.isdir(sChildPath):
print_directory_contents(sChildPath)
else:
print(sChildPath)

- 659
- 1
- 13
- 30
#import modules
import os
_CURRENT_DIR = '.'
def rec_tree_traverse(curr_dir, indent):
"recurcive function to traverse the directory"
#print "[traverse_tree]"
try :
dfList = [os.path.join(curr_dir, f_or_d) for f_or_d in os.listdir(curr_dir)]
except:
print "wrong path name/directory name"
return
for file_or_dir in dfList:
if os.path.isdir(file_or_dir):
#print "dir : ",
print indent, file_or_dir,"\\"
rec_tree_traverse(file_or_dir, indent*2)
if os.path.isfile(file_or_dir):
#print "file : ",
print indent, file_or_dir
#end if for loop
#end of traverse_tree()
def main():
base_dir = _CURRENT_DIR
rec_tree_traverse(base_dir," ")
raw_input("enter any key to exit....")
#end of main()
if __name__ == '__main__':
main()

- 41,899
- 19
- 136
- 174

- 25
- 1
-
5This question already has a perfectly good answer, there is no need to answer again – Mike Pennington Nov 23 '12 at 11:57
FYI Add a filter of extension or ext file import os
path = '.'
for dirname, dirnames, filenames in os.walk(path):
# print path to all filenames with extension py.
for filename in filenames:
fname_path = os.path.join(dirname, filename)
fext = os.path.splitext(fname_path)[1]
if fext == '.py':
print fname_path
else:
continue

- 1,288
- 2
- 13
- 20
If figured I'd throw this in. Simple and dirty way to do wildcard searches.
import re
import os
[a for a in os.listdir(".") if re.search("^.*\.py$",a)]

- 339
- 2
- 6
Here is a one line Pythonic version:
import os
dir = 'given_directory_name'
filenames = [os.path.join(os.path.dirname(os.path.abspath(__file__)),dir,i) for i in os.listdir(dir)]
This code lists the full path of all files and directories in the given directory name.

- 7,258
- 3
- 18
- 26
-
Thanks Saleh, but your code didn't worked fully, and the one worked was modified as follows: 'dir = 'given_directory_name' filenames = [os.path.abspath(os.path.join(dir,i)) for i in os.listdir(dir)]' – HassanSh__3571619 Mar 18 '18 at 16:24
I know this is an old question. This is a neat way I came across if you are on a liunx machine.
import subprocess
print(subprocess.check_output(["ls", "/"]).decode("utf8"))

- 301
- 1
- 4
- 12
-
3This is *hugely* inefficient as well as error-prone. Python knows full well how to traverse a directory listing and [you should not use `ls` in scripts ever anyway.](https://mywiki.wooledge.org/ParsingLs) – tripleee Nov 24 '20 at 08:23
Easiest way:
list_output_files = [os.getcwd()+"\\"+f for f in os.listdir(os.getcwd())]

- 848
- 7
- 12