ChatGPT解决这个技术问题 Extra ChatGPT

Directory-tree listing in Python

How do I get a list of all files (and directories) in a given directory in Python?

recursively or not? Clarify please. For non recursive solution see: stackoverflow.com/questions/973473/…

L
Løiten

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')

And if you run this code (as is) from the Python Shell, recall that Ctrl+C will halt output to said shell. ;)
This will recursively list files and directories
You can even edit the dirnames list to prevent it from recursing down some paths.
@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 docs.python.org/2/library/os.html#os.walk
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'
M
Matt

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


well 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, 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.
The 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).
listdir gives you the only the filename in the directory, is there a method available to get full path?
@greperror You can use os.path.abspath for getting the full path. Also, to check if a given path is a file, use the os.path.isfile or os.path.isdir.
g
giltay

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)]

A generator would be better.
@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.
It's been ten years, but I think I did it this way because os.listdir() returns a list and I was imitating that.
T
Tim Cooper
import os

for filename in os.listdir("C:\\temp"):
    print  filename

r'C:\temp' is clearer and preferred to "C:\\temp" Rawstrings are preferable to escpaing backslashes.
@smci: Actually "C:/temp" is what would be preferred.
@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: 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. ;¬)
k
kenny

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.


that's really awesome! can you have negation in those matching expression? like everything except files matching THIS pattern?
@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 to another question.
G
Georgy

For files in current working directory without specifying a path

Python 2.7:

import os
os.listdir('.')

Python 3.x:

import os
os.listdir()

p
paxdiablo

Try this:

import os
for top, dirs, files in os.walk('./'):
    for nm in files:       
        print os.path.join(top, nm)

In one line: [top + os.sep + f for top, dirs, files in os.walk('./') for f in files]
A
Arnaldo P. Figueira Figueira

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)

S
Steve Tarver

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'),

S
Sam Watkins

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:])

K
Khaino

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.

Python Docs


t
tripleee

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)]

f
fivetentaylor

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


A
Alejandro Blasco

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)])

M
Mike Pennington
#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()

This question already has a perfectly good answer, there is no need to answer again
m
moylop260

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

b
bng44270

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)]

H
Heenashree Khandelwal

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)

s
salehinejad

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.


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)]'
a
apeter

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"))

This 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.
M
Manav Patadia

Easiest way:

list_output_files = [os.getcwd()+"\\"+f for f in os.listdir(os.getcwd())]