web-dev-qa-db-de.com

Wie liste ich alle Dateien eines Verzeichnisses auf?

Wie kann ich alle Dateien eines Verzeichnisses in Python auflisten und sie einem list hinzufügen?

3474
duhhunjonn

Mit os.listdir() erhalten Sie alles, was sich in einem Verzeichnis befindet - Dateien und Verzeichnisse.

Wenn Sie nur Dateien möchten, können Sie diese entweder mit os.path nach unten filtern:

_from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
_

oder Sie können os.walk() verwenden, um zwei Listen für jedes Verzeichnis zu erhalten, das es besucht - aufgeteilt in Dateien und Verzeichnisse für Sie. Wenn Sie nur das oberste Verzeichnis möchten, können Sie es beim ersten Mal unterbrechen

_from os import walk

f = []
for (dirpath, dirnames, filenames) in walk(mypath):
    f.extend(filenames)
    break
_
3578
pycruft

Ich bevorzuge die Verwendung des Moduls glob , da es den Mustervergleich und die Erweiterung ausführt.

import glob
print(glob.glob("/home/adam/*.txt"))

Es wird eine Liste mit den abgefragten Dateien zurückgegeben:

['/home/adam/file1.txt', '/home/adam/file2.txt', .... ]
1440
adamk
import os
os.listdir("somedirectory")

gibt eine Liste aller Dateien und Verzeichnisse in "somedirectory" zurück.

697
sepp2k

Eine Liste der Dateien erhalten Sie mit Python 2 und 3


Ich habe ein kurzes Video gemacht, das hier verfügbar ist:  Python: wie man eine Liste von Dateien in einem Verzeichnis erhält


os.listdir()

So erhalten Sie alle Dateien (und Verzeichnisse) im aktuellen Verzeichnis (Python 3)

Im Folgenden finden Sie einfache Methoden zum Abrufen nur der Dateien im aktuellen Verzeichnis mithilfe von os und der Funktion listdir() in Python wird die Datei nicht im Unterverzeichnis haben, dafür können Sie walk verwenden (wird später besprochen).

 import os
 arr = os.listdir()
 print(arr)

 >>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

glob

Ich fand es einfacher, die Datei desselben Typs oder mit etwas gemeinsamem auszuwählen. Schauen Sie sich das folgende Beispiel an:

import glob

txtfiles = []
for file in glob.glob("*.txt"):
    txtfiles.append(file)

glob mit Listenverständnis

import glob

mylist = [f for f in glob.glob("*.txt")]

glob mit einer Funktion

import glob

def filebrowser():
    return [f for f in glob.glob("*")]

x = filebrowser()
print(x)

>>> ['example.txt', 'fb.py', 'filebrowser.py', 'help']

glob Erweitert den vorherigen Code

Die Funktion gibt jetzt eine Liste der Dateien zurück, die mit der als Argument übergebenen Zeichenfolge übereinstimmen

import glob

def filebrowser(Word=""):
    """Returns a list with all files with the Word/extension in it"""
    file = []
    for f in glob.glob("*"):
        if Word in f:
            file.append(f)
            return file

flist = filebrowser("example")
print(flist)
flist = filebrowser(".py")
print(flist)

>>> ['example.txt']
>>> ['fb.py', 'filebrowser.py']

Den vollständigen Pfadnamen mit os.path.abspath erhalten

Wie Sie bemerkt haben, ist im obigen Code nicht der vollständige Pfad der Datei angegeben. Wenn Sie den absoluten Pfad benötigen, können Sie eine andere Funktion des Moduls os.path mit dem Namen _getfullpathname verwenden und die Datei, die Sie von os.listdir() erhalten, als Argument verwenden. Es gibt andere Möglichkeiten, den vollständigen Pfad zu erhalten, wie wir später prüfen werden (ich habe, wie von mexmex vorgeschlagen, _getfullpathname durch abspath ersetzt).

 import os
 files_path = [os.path.abspath(x) for x in os.listdir()]
 print(files_path)

 >>> ['F:\\documenti\applications.txt', 'F:\\documenti\collections.txt']

Mit walk den vollständigen Pfadnamen eines Dateityps in alle Unterverzeichnisse abrufen

Ich finde das sehr nützlich, um Dinge in vielen Verzeichnissen zu finden, und es hat mir geholfen, eine Datei zu finden, über die ich mich nicht an den Namen erinnere:

import os

# Getting the current work directory (cwd)
thisdir = os.getcwd()

# r=root, d=directories, f = files
for r, d, f in os.walk(thisdir):
    for file in f:
        if ".docx" in file:
            print(os.path.join(r, file))

os.listdir(): ruft Dateien im aktuellen Verzeichnis ab (Python 2)

Wenn Sie in Python 2 die Liste der Dateien im aktuellen Verzeichnis anzeigen möchten, müssen Sie das Argument '.' oder os.getcwd () in der Methode os.listdir.

 import os
 arr = os.listdir('.')
 print(arr)

 >>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Im Verzeichnisbaum nach oben gehen

# Method 1
x = os.listdir('..')

# Method 2
x= os.listdir('/')

Dateien abrufen: os.listdir() in einem bestimmten Verzeichnis (Python 2 und 3)

 import os
 arr = os.listdir('F:\\python')
 print(arr)

 >>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Abrufen von Dateien eines bestimmten Unterverzeichnisses mit os.listdir()

import os

x = os.listdir("./content")

os.walk('.') - aktuelles Verzeichnis

 import os
 arr = next(os.walk('.'))[2]
 print(arr)

 >>> ['5bs_Turismo1.pdf', '5bs_Turismo1.pptx', 'esperienza.txt']

next(os.walk('.')) und os.path.join('dir', 'file')

 import os
 arr = []
 for d,r,f in next(os.walk("F:\\_python")):
     for file in f:
         arr.append(os.path.join(r,file))

 for f in arr:
     print(files)

>>> F:\\_python\\dict_class.py
>>> F:\\_python\\programmi.txt

next(os.walk('F:\\') - Holen Sie sich das vollständige Verständnis der Pfadliste

 [os.path.join(r,file) for r,d,f in next(os.walk("F:\\_python")) for file in f]

 >>> ['F:\\_python\\dict_class.py', 'F:\\_python\\programmi.txt']

os.walk - Erhalte den vollständigen Pfad - alle Dateien in Unterverzeichnissen **

x = [os.path.join(r,file) for r,d,f in os.walk("F:\\_python") for file in f]
print(x)

>>> ['F:\\_python\\dict.py', 'F:\\_python\\progr.txt', 'F:\\_python\\readl.py']

os.listdir() - Nur TXT-Dateien abrufen

 arr_txt = [x for x in os.listdir() if x.endswith(".txt")]
 print(arr_txt)

 >>> ['work.txt', '3ebooks.txt']

Verwenden Sie glob, um den vollständigen Pfad der Dateien abzurufen

Wenn ich den absoluten Pfad der Dateien benötigen sollte:

from path import path
from glob import glob
x = [path(f).abspath() for f in glob("F:\\*.txt")]
for f in x:
    print(f)

>>> F:\acquistionline.txt
>>> F:\acquisti_2018.txt
>>> F:\bootstrap_jquery_ecc.txt

Verwenden Sie os.path.isfile, um Verzeichnisse in der Liste zu vermeiden

import os.path
listOfFiles = [f for f in os.listdir() if os.path.isfile(f)]
print(listOfFiles)

>>> ['a simple game.py', 'data.txt', 'decorator.py']

Verwenden von pathlib aus Python 3.4

import pathlib

flist = []
for p in pathlib.Path('.').iterdir():
    if p.is_file():
        print(p)
        flist.append(p)

 >>> error.PNG
 >>> exemaker.bat
 >>> guiprova.mp3
 >>> setup.py
 >>> speak_gui2.py
 >>> thumb.PNG

Mit list comprehension:

flist = [p for p in pathlib.Path('.').iterdir() if p.is_file()]

Verwenden Sie alternativ pathlib.Path() anstelle von pathlib.Path(".")

Verwenden Sie die Methode glob in pathlib.Path ()

import pathlib

py = pathlib.Path().glob("*.py")
for file in py:
    print(file)

>>> stack_overflow_list.py
>>> stack_overflow_list_tkinter.py

Holen Sie sich alle und nur Dateien mit os.walk

import os
x = [i[2] for i in os.walk('.')]
y=[]
for t in x:
    for f in t:
        y.append(f)
print(y)

>>> ['append_to_list.py', 'data.txt', 'data1.txt', 'data2.txt', 'data_180617', 'os_walk.py', 'READ2.py', 'read_data.py', 'somma_defaltdic.py', 'substitute_words.py', 'sum_data.py', 'data.txt', 'data1.txt', 'data_180617']

Holen Sie sich nur Dateien mit next und gehen Sie in ein Verzeichnis

 import os
 x = next(os.walk('F://python'))[2]
 print(x)

 >>> ['calculator.bat','calculator.py']

Holen Sie sich nur Verzeichnisse mit next und gehen Sie in ein Verzeichnis

 import os
 next(os.walk('F://python'))[1] # for the current dir use ('.')

 >>> ['python3','others']

Holen Sie sich alle Unterverzeichnisnamen mit walk

for r,d,f in os.walk("F:\\_python"):
    for dirs in d:
        print(dirs)

>>> .vscode
>>> pyexcel
>>> pyschool.py
>>> subtitles
>>> _metaprogramming
>>> .ipynb_checkpoints

os.scandir() von Python 3.5 und höher

import os
x = [f.name for f in os.scandir() if f.is_file()]
print(x)

>>> ['calculator.bat','calculator.py']

# Another example with scandir (a little variation from docs.python.org)
# This one is more efficient than os.listdir.
# In this case, it shows the files only in the current directory
# where the script is executed.

import os
with os.scandir() as i:
    for entry in i:
        if entry.is_file():
            print(entry.name)

>>> ebookmaker.py
>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speakgui4.py
>>> speak_gui2.py
>>> speak_gui3.py
>>> thumb.PNG

Beispiele:

Ex. 1: Wie viele Dateien befinden sich in den Unterverzeichnissen?

In diesem Beispiel wird nach der Anzahl der Dateien gesucht, die in allen Verzeichnissen und deren Unterverzeichnissen enthalten sind.

import os

def count(dir, counter=0):
    "returns number of files in dir and subdirs"
    for pack in os.walk(dir):
        for f in pack[2]:
            counter += 1
    return dir + " : " + str(counter) + "files"

print(count("F:\\python"))

>>> 'F:\\\python' : 12057 files'

Beispiel 2: Wie kopiere ich alle Dateien von einem Verzeichnis in ein anderes?

Ein Skript, um auf Ihrem Computer Ordnung zu schaffen, alle Dateien eines Typs zu finden (Standard: pptx) und sie in einen neuen Ordner zu kopieren.

import os
import shutil
from path import path

destination = "F:\\file_copied"
# os.makedirs(destination)

def copyfile(dir, filetype='pptx', counter=0):
    "Searches for pptx (or other - pptx is the default) files and copies them"
    for pack in os.walk(dir):
        for f in pack[2]:
            if f.endswith(filetype):
                fullpath = pack[0] + "\\" + f
                print(fullpath)
                shutil.copy(fullpath, destination)
                counter += 1
    if counter > 0:
        print('-' * 30)
        print("\t==> Found in: `" + dir + "` : " + str(counter) + " files\n")

for dir in os.listdir():
    "searches for folders that starts with `_`"
    if dir[0] == '_':
        # copyfile(dir, filetype='pdf')
        copyfile(dir, filetype='txt')


>>> _compiti18\Compito Contabilità 1\conti.txt
>>> _compiti18\Compito Contabilità 1\modula4.txt
>>> _compiti18\Compito Contabilità 1\moduloa4.txt
>>> ------------------------
>>> ==> Found in: `_compiti18` : 3 files

Ex. 3: Wie bekomme ich alle Dateien in einer TXT-Datei

Falls Sie eine txt-Datei mit allen Dateinamen erstellen möchten:

import os
mylist = ""
with open("filelist.txt", "w", encoding="utf-8") as file:
    for eachfile in os.listdir():
        mylist += eachfile + "\n"
    file.write(mylist)

Beispiel: txt mit allen Dateien einer Festplatte

"""
We are going to save a txt file with all the files in your directory.
We will use the function walk()
"""

import os

# see all the methods of os
# print(*dir(os), sep=", ")
listafile = []
percorso = []
with open("lista_file.txt", "w", encoding='utf-8') as testo:
    for root, dirs, files in os.walk("D:\\"):
        for file in files:
            listafile.append(file)
            percorso.append(root + "\\" + file)
            testo.write(file + "\n")
listafile.sort()
print("N. of files", len(listafile))
with open("lista_file_ordinata.txt", "w", encoding="utf-8") as testo_ordinato:
    for file in listafile:
        testo_ordinato.write(file + "\n")

with open("percorso.txt", "w", encoding="utf-8") as file_percorso:
    for file in percorso:
        file_percorso.write(file + "\n")

os.system("lista_file.txt")
os.system("lista_file_ordinata.txt")
os.system("percorso.txt")

Alle Dateien von C:\in einer Textdatei

Dies ist eine kürzere Version des vorherigen Codes. Ändern Sie den Ordner, in dem die Dateien gesucht werden sollen, wenn Sie an einer anderen Position beginnen müssen. Dieser Code generiert auf meinem Computer eine Textdatei mit einer Größe von 50 MB und weniger als 500.000 Zeilen mit Dateien mit dem vollständigen Pfad.

import os

with open("file.txt", "w", encoding="utf-8") as filewrite:
    for r, d, f in os.walk("C:\\"):
        for file in f:
            filewrite.write(f"{r + file}\n")

So schreiben Sie eine Datei mit allen Pfaden in einen Ordner eines Typs

Mit dieser Funktion können Sie eine txt-Datei erstellen, die den Namen eines Dateityps enthält, nach dem Sie suchen (z. B. pngfile.txt) und den vollständigen Pfad aller Dateien dieses Typs enthält. Es kann manchmal nützlich sein, denke ich.

import os

def searchfiles(extension='.ttf', folder='H:\\'):
    "Create a txt file with all the file of a type"
    with open(extension[1:] + "file.txt", "w", encoding="utf-8") as filewrite:
        for r, d, f in os.walk(folder):
            for file in f:
                if file.endswith(extension):
                    filewrite.write(f"{r + file}\n")

# looking for png file (fonts) in the hard disk H:\
searchfiles('.png', 'H:\\')

>>> H:\4bs_18\Dolphins5.png
>>> H:\4bs_18\Dolphins6.png
>>> H:\4bs_18\Dolphins7.png
>>> H:\5_18\marketing html\assets\imageslogo2.png
>>> H:\7z001.png
>>> H:\7z002.png
571
Giovanni Python

Eine einzeilige Lösung, um nur eine Liste von Dateien (keine Unterverzeichnisse) zu erhalten:

filenames = next(os.walk(path))[2]

oder absolute Pfadnamen:

paths = [os.path.join(path,fn) for fn in next(os.walk(path))[2]]
150
Remi

Abrufen vollständiger Dateipfade aus einem Verzeichnis und allen seinen Unterverzeichnissen

import os

def get_filepaths(directory):
    """
    This function will generate the file names in a directory 
    tree by walking the tree either top-down or bottom-up. For each 
    directory in the tree rooted at directory top (including top itself), 
    it yields a 3-Tuple (dirpath, dirnames, filenames).
    """
    file_paths = []  # List which will store all of the full filepaths.

    # Walk the tree.
    for root, directories, files in os.walk(directory):
        for filename in files:
            # Join the two strings in order to form the full filepath.
            filepath = os.path.join(root, filename)
            file_paths.append(filepath)  # Add it to the list.

    return file_paths  # Self-explanatory.

# Run the above function and store its results in a variable.   
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")

  • Der Pfad, den ich in der obigen Funktion angegeben habe, enthielt drei Dateien - zwei davon im Stammverzeichnis und eine weitere in einem Unterordner namens "SUBFOLDER". Sie können jetzt folgende Aufgaben ausführen:
  • print full_file_paths, der die Liste druckt:

    • ['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']

Wenn Sie möchten, können Sie den Inhalt öffnen und lesen oder sich nur auf Dateien mit der Erweiterung ".dat" konzentrieren, wie im folgenden Code:

for f in full_file_paths:
  if f.endswith(".dat"):
    print f

/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat

121
Johnny

Seit Version 3.4 gibt es dafür eingebaute Iteratoren , die viel effizienter sind als os.listdir() :

pathlib : Neu in Version 3.4.

>>> import pathlib
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]

Gemäß PEP 428 besteht das Ziel der Bibliothek pathlib darin, eine einfache Hierarchie von Klassen bereitzustellen, um Dateisystempfade und die allgemeinen Vorgänge zu behandeln, die Benutzer über sie ausführen.

os.scandir() : Neu in Version 3.5.

>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]

Beachten Sie, dass os.walk()os.scandir() anstelle von os.listdir() ab Version 3.5 verwendet und die Geschwindigkeit gemäß PEP) um das 2- bis 20-fache erhöht wurde 471 .

Lassen Sie mich auch empfehlen, den Kommentar von ShadowRanger weiter unten zu lesen.

73
SzieberthAdam

Vorbemerkungen

  • Obwohl der Fragentext eine klare Unterscheidung zwischen den Begriffen file und directory enthält, wird möglicherweise argumentiert, dass es sich bei Verzeichnissen tatsächlich um spezielle Dateien handelt
  • Die Anweisung: " alle Dateien eines Verzeichnisses " kann auf zwei Arten interpretiert werden:
    1. Alle direkt ​​(oder Stufe 1) Nachkommen nur
    2. Alle Nachkommen im gesamten Verzeichnisbaum (einschließlich der in Unterverzeichnissen)
  • Als die Frage gestellt wurde, stelle ich mir vor, dass Python 2 [~ # ~] lts [~ # ~] Version, jedoch werden die Codebeispiele von Python (. 5) (I Ich halte sie als Python 2 konform, und jeden Code, der zu Python gehört, den ich veröffentlichen werde. ist von v3.5.4 - sofern nicht anders angegeben). Dies hat Konsequenzen für ein anderes Keyword in der Frage: " füge sie in eine Liste":

    • In Versionen vor Python 2.2 wurden Sequenzen (iterables) hauptsächlich durch Listen (Tupel, Mengen, ...) dargestellt.
    • In Python 2.2 wurde das Konzept von generator ( [Python.Wiki]: Generators ) mit freundlicher Genehmigung von [Python 3]: Die Yield-Anweisung ) - wurde eingeführt. Mit der Zeit tauchten Generator-Gegenstücke für Funktionen auf, die Listen zurückgaben/mit ihnen arbeiteten
    • In Python 3 ist generator das Standardverhalten
    • Sie sind sich nicht sicher, ob die Rückgabe einer Liste weiterhin obligatorisch ist (oder ein Generator dies auch tun würde). Wenn Sie jedoch einen Generator an den Konstruktor list übergeben, wird eine Liste daraus erstellt (und auch verbrauchen es). Das folgende Beispiel veranschaulicht die Unterschiede in [Python 3]: map ( - Funktion, iterabel, ... )
    >>> import sys
    >>> sys.version
    '2.7.10 (default, Mar  8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]'
    >>> m = map(lambda x: x, [1, 2, 3])  # Just a dummy lambda function
    >>> m, type(m)
    ([1, 2, 3], <type 'list'>)
    >>> len(m)
    3
    


    >>> import sys
    >>> sys.version
    '3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]'
    >>> m = map(lambda x: x, [1, 2, 3])
    >>> m, type(m)
    (<map object at 0x000001B4257342B0>, <class 'map'>)
    >>> len(m)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: object of type 'map' has no len()
    >>> lm0 = list(m)  # Build a list from the generator
    >>> lm0, type(lm0)
    ([1, 2, 3], <class 'list'>)
    >>>
    >>> lm1 = list(m)  # Build a list from the same generator
    >>> lm1, type(lm1)  # Empty list now - generator already consumed
    ([], <class 'list'>)
    
  • Die Beispiele basieren auf einem Verzeichnis namens root_dir mit der folgenden Struktur (dieses Beispiel ist für Win , aber ich verwende der gleiche Baum auf Lnx auch):

    E:\Work\Dev\StackOverflow\q003207219>tree /f "root_dir"
    Folder PATH listing for volume Work
    Volume serial number is 00000029 3655:6FED
    E:\WORK\DEV\STACKOVERFLOW\Q003207219\ROOT_DIR
    ¦   file0
    ¦   file1
    ¦
    +---dir0
    ¦   +---dir00
    ¦   ¦   ¦   file000
    ¦   ¦   ¦
    ¦   ¦   +---dir000
    ¦   ¦           file0000
    ¦   ¦
    ¦   +---dir01
    ¦   ¦       file010
    ¦   ¦       file011
    ¦   ¦
    ¦   +---dir02
    ¦       +---dir020
    ¦           +---dir0200
    +---dir1
    ¦       file10
    ¦       file11
    ¦       file12
    ¦
    +---dir2
    ¦   ¦   file20
    ¦   ¦
    ¦   +---dir20
    ¦           file200
    ¦
    +---dir3
    


Lösungen

Programmatische Ansätze:

  1. [Python 3]: os .listdir ( path = '.' )

    Gibt eine Liste zurück, die die Namen der Einträge in dem durch path angegebenen Verzeichnis enthält. Die Liste ist in beliebiger Reihenfolge und enthält nicht die speziellen Einträge '.' Und '..' ...


    >>> import os
    >>> root_dir = "root_dir"  # Path relative to current dir (os.getcwd())
    >>>
    >>> os.listdir(root_dir)  # List all the items in root_dir
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [item for item in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, item))]  # Filter items and only keep files (strip out directories)
    ['file0', 'file1']
    

    Ein ausführlicheres Beispiel ( code_os_listdir.py ):

    import os
    from pprint import pformat
    
    
    def _get_dir_content(path, include_folders, recursive):
        entries = os.listdir(path)
        for entry in entries:
            entry_with_path = os.path.join(path, entry)
            if os.path.isdir(entry_with_path):
                if include_folders:
                    yield entry_with_path
                if recursive:
                    for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive):
                        yield sub_entry
            else:
                yield entry_with_path
    
    
    def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True):
        path_len = len(path) + len(os.path.sep)
        for item in _get_dir_content(path, include_folders, recursive):
            yield item if prepend_folder_name else item[path_len:]
    
    
    def _get_dir_content_old(path, include_folders, recursive):
        entries = os.listdir(path)
        ret = list()
        for entry in entries:
            entry_with_path = os.path.join(path, entry)
            if os.path.isdir(entry_with_path):
                if include_folders:
                    ret.append(entry_with_path)
                if recursive:
                    ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive))
            else:
                ret.append(entry_with_path)
        return ret
    
    
    def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True):
        path_len = len(path) + len(os.path.sep)
        return [item if prepend_folder_name else item[path_len:] for item in _get_dir_content_old(path, include_folders, recursive)]
    
    
    def main():
        root_dir = "root_dir"
        ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
        lret0 = list(ret0)
        print(ret0, len(lret0), pformat(lret0))
        ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)
        print(len(ret1), pformat(ret1))
    
    
    if __== "__main__":
        main()
    

    Notizen:

    • Es gibt zwei Implementierungen:
      • Eine, die Generatoren verwendet (hier scheint es natürlich nutzlos zu sein, da ich das Ergebnis sofort in eine Liste konvertiere)
      • Der Klassiker (Funktionsnamen enden mit _ old)
    • Rekursion wird verwendet (um in Unterverzeichnisse zu gelangen)
    • Für jede Implementierung gibt es zwei Funktionen:
      • Eine, die mit einem - Unterstrich (_) beginnt: "privat" (sollte nicht direkt aufgerufen werden) - das erledigt die ganze Arbeit
      • Die öffentliche (Wrapper über der vorherigen): Sie entfernt nur den anfänglichen Pfad (falls erforderlich) von den zurückgegebenen Einträgen. Es ist eine hässliche Implementierung, aber es ist die einzige Idee, mit der ich an diesem Punkt kommen könnte
    • In Bezug auf die Leistung sind Generatoren im Allgemeinen etwas schneller (unter Berücksichtigung der beiden Zeiten creation und iteration ), aber das habe ich nicht getan Testen Sie sie in rekursiven Funktionen, und ich iteriere auch innerhalb der Funktion über innere Generatoren - ich weiß nicht, wie leistungsfreundlich das ist
    • Spielen Sie mit den Argumenten, um unterschiedliche Ergebnisse zu erzielen


    Ausgabe:

    (py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" "code_os_listdir.py"
    <generator object get_dir_content at 0x000001BDDBB3DF10> 22 ['root_dir\\dir0',
     'root_dir\\dir0\\dir00',
     'root_dir\\dir0\\dir00\\dir000',
     'root_dir\\dir0\\dir00\\dir000\\file0000',
     'root_dir\\dir0\\dir00\\file000',
     'root_dir\\dir0\\dir01',
     'root_dir\\dir0\\dir01\\file010',
     'root_dir\\dir0\\dir01\\file011',
     'root_dir\\dir0\\dir02',
     'root_dir\\dir0\\dir02\\dir020',
     'root_dir\\dir0\\dir02\\dir020\\dir0200',
     'root_dir\\dir1',
     'root_dir\\dir1\\file10',
     'root_dir\\dir1\\file11',
     'root_dir\\dir1\\file12',
     'root_dir\\dir2',
     'root_dir\\dir2\\dir20',
     'root_dir\\dir2\\dir20\\file200',
     'root_dir\\dir2\\file20',
     'root_dir\\dir3',
     'root_dir\\file0',
     'root_dir\\file1']
    11 ['dir0\\dir00\\dir000\\file0000',
     'dir0\\dir00\\file000',
     'dir0\\dir01\\file010',
     'dir0\\dir01\\file011',
     'dir1\\file10',
     'dir1\\file11',
     'dir1\\file12',
     'dir2\\dir20\\file200',
     'dir2\\file20',
     'file0',
     'file1']
    


  1. [Python 3]: os .scandir ( path = '.' ) ( Python .5 +, Backport: [PyPI]: scandir )

    Gibt einen Iterator von os.DirEntry -Objekten zurück, die den Einträgen in dem durch path angegebenen Verzeichnis entsprechen. Die Einträge werden in beliebiger Reihenfolge ausgegeben und die Sondereinträge '.' Und '..' Sind nicht enthalten.

    Die Verwendung von scandir () anstelle von listdir () kann die Leistung von Code erheblich verbessern, der auch Dateityp- oder Dateiattributinformationen benötigt, da os.DirEntry -Objekte machen diese Informationen verfügbar, wenn das Betriebssystem sie beim Durchsuchen eines Verzeichnisses bereitstellt. Alle os.DirEntry -Methoden können einen Systemaufruf ausführen, in der Regel jedoch is_dir () und is_file () erfordern nur einen Systemaufruf für symbolische Verknüpfungen; os.DirEntry.stat () erfordert unter Unix immer einen Systemaufruf, unter Windows jedoch nur einen für symbolische Verknüpfungen.


    >>> import os
    >>> root_dir = os.path.join(".", "root_dir")  # Explicitly prepending current directory
    >>> root_dir
    '.\\root_dir'
    >>>
    >>> scandir_iterator = os.scandir(root_dir)
    >>> scandir_iterator
    <nt.ScandirIterator object at 0x00000268CF4BC140>
    >>> [item.path for item in scandir_iterator]
    ['.\\root_dir\\dir0', '.\\root_dir\\dir1', '.\\root_dir\\dir2', '.\\root_dir\\dir3', '.\\root_dir\\file0', '.\\root_dir\\file1']
    >>>
    >>> [item.path for item in scandir_iterator]  # Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension)
    []
    >>>
    >>> scandir_iterator = os.scandir(root_dir)  # Reinitialize the generator
    >>> for item in scandir_iterator :
    ...     if os.path.isfile(item.path):
    ...             print(item.name)
    ...
    file0
    file1
    

    Notizen:

    • Es ist ähnlich wie os.listdir
    • Aber es ist auch flexibler (und bietet mehr Funktionalität), mehr Python ic (und in einigen Fällen schneller)


  1. [Python 3]: os .walk ( top, topdown = True, onerror = None, followlinks = False )

    Generieren Sie die Dateinamen in einem Verzeichnisbaum, indem Sie den Baum von oben nach unten oder von unten nach oben durchgehen. Für jedes Verzeichnis in der Struktur, die im Verzeichnis top (einschließlich top selbst) verwurzelt ist, wird ein 3-Tupel (dirpath, dirnames, filenames).


    >>> import os
    >>> root_dir = os.path.join(os.getcwd(), "root_dir")  # Specify the full path
    >>> root_dir
    'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir'
    >>>
    >>> walk_generator = os.walk(root_dir)
    >>> root_dir_entry = next(walk_generator)  # First entry corresponds to the root dir (passed as an argument)
    >>> root_dir_entry
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir', ['dir0', 'dir1', 'dir2', 'dir3'], ['file0', 'file1'])
    >>>
    >>> root_dir_entry[1] + root_dir_entry[2]  # Display dirs and files (direct descendants) in a single list
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [os.path.join(root_dir_entry[0], item) for item in root_dir_entry[1] + root_dir_entry[2]]  # Display all the entries in the previous list by their full path
    ['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1']
    >>>
    >>> for entry in walk_generator:  # Display the rest of the elements (corresponding to every subdir)
    ...     print(entry)
    ...
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', ['dir00', 'dir01', 'dir02'], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00', ['dir000'], ['file000'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000', [], ['file0000'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01', [], ['file010', 'file011'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02', ['dir020'], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020', ['dir0200'], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200', [], [])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', [], ['file10', 'file11', 'file12'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', ['dir20'], ['file20'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20', [], ['file200'])
    ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', [], [])
    

    Notizen:

    • In den Szenen wird os.scandir Verwendet (os.listdir Bei älteren Versionen)
    • Es erledigt das schwere Heben, indem es sich in Unterordnern wiederholt


  1. [Python 3]: glob .glob ( Pfadname, *, rekursiv = Falsch ) ( [Python 3]: glob .iglob ( Pfadname, *, rekursiv = False ) )

    Gibt eine möglicherweise leere Liste von Pfadnamen zurück, die mit Pfadname übereinstimmen. Dies muss eine Zeichenfolge sein, die eine Pfadangabe enthält. Pfadname kann entweder absolut (wie /usr/src/Python-1.5/Makefile) oder relativ (wie ../../Tools/*/*.gif) sein und Platzhalter im Shell-Stil enthalten. Defekte Symlinks sind in den Ergebnissen enthalten (wie in der Shell).
    ...
    Geändert in Version 3.5 : Unterstützung für rekursive Globs mit "**".


    >>> import glob, os
    >>> wildcard_pattern = "*"
    >>> root_dir = os.path.join("root_dir", wildcard_pattern)  # Match every file/dir name
    >>> root_dir
    'root_dir\\*'
    >>>
    >>> glob_list = glob.glob(root_dir)
    >>> glob_list
    ['root_dir\\dir0', 'root_dir\\dir1', 'root_dir\\dir2', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1']
    >>>
    >>> [item.replace("root_dir" + os.path.sep, "") for item in glob_list]  # Strip the dir name and the path separator from begining
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> for entry in glob.iglob(root_dir + "*", recursive=True):
    ...     print(entry)
    ...
    root_dir\
    root_dir\dir0
    root_dir\dir0\dir00
    root_dir\dir0\dir00\dir000
    root_dir\dir0\dir00\dir000\file0000
    root_dir\dir0\dir00\file000
    root_dir\dir0\dir01
    root_dir\dir0\dir01\file010
    root_dir\dir0\dir01\file011
    root_dir\dir0\dir02
    root_dir\dir0\dir02\dir020
    root_dir\dir0\dir02\dir020\dir0200
    root_dir\dir1
    root_dir\dir1\file10
    root_dir\dir1\file11
    root_dir\dir1\file12
    root_dir\dir2
    root_dir\dir2\dir20
    root_dir\dir2\dir20\file200
    root_dir\dir2\file20
    root_dir\dir3
    root_dir\file0
    root_dir\file1
    

    Notizen:

    • Verwendet os.listdir
    • Bei großen Bäumen (insbesondere wenn recursive aktiviert ist) wird iglob bevorzugt
    • Ermöglicht erweitertes Filtern basierend auf dem Namen (aufgrund des Platzhalters)


  1. [Python 3]: Klasse pathlib .Path ( * Pathsegments ) ( Python .4 +, Backport: [PyPI]: pathlib2 )

    >>> import pathlib
    >>> root_dir = "root_dir"
    >>> root_dir_instance = pathlib.Path(root_dir)
    >>> root_dir_instance
    WindowsPath('root_dir')
    >>> root_dir_instance.name
    'root_dir'
    >>> root_dir_instance.is_dir()
    True
    >>>
    >>> [item.name for item in root_dir_instance.glob("*")]  # Wildcard searching for all direct descendants
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [os.path.join(item.parent.name, item.name) for item in root_dir_instance.glob("*") if not item.is_dir()]  # Display paths (including parent) for files only
    ['root_dir\\file0', 'root_dir\\file1']
    

    Notizen:

    • Dies ist one ein Weg, um unser Ziel zu erreichen
    • Dies ist der [~ # ~] oop [~ # ~] -Stil für den Umgang mit Pfaden
    • Bietet viele Funktionen


  1. [Python 2]: dircache.listdir (path) ( Python 2 only)


    def listdir(path):
        """List directory contents, using cache."""
        try:
            cached_mtime, list = cache[path]
            del cache[path]
        except KeyError:
            cached_mtime, list = -1, []
        mtime = os.stat(path).st_mtime
        if mtime != cached_mtime:
            list = os.listdir(path)
            list.sort()
        cache[path] = mtime, list
        return list
    


  1. [man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3 ) über [Python 3]: ctypes - Eine fremde Funktionsbibliothek für Python ( [~ # ~] posix [~ # ~] spezifisch)

    ctypes ist eine fremde Funktionsbibliothek für Python. Es bietet C-kompatible Datentypen und ermöglicht das Aufrufen von Funktionen in DLLs oder gemeinsam genutzten Bibliotheken. Es kann verwendet werden, um diese Bibliotheken in Python zu verpacken.

    code_ctypes.py :

    #!/usr/bin/env python3
    
    import sys
    from ctypes import Structure, \
        c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \
        CDLL, POINTER, \
        create_string_buffer, get_errno, set_errno, cast
    
    
    DT_DIR = 4
    DT_REG = 8
    
    char256 = c_char * 256
    
    
    class LinuxDirent64(Structure):
        _fields_ = [
            ("d_ino", c_ulonglong),
            ("d_off", c_longlong),
            ("d_reclen", c_ushort),
            ("d_type", c_ubyte),
            ("d_name", char256),
        ]
    
    LinuxDirent64Ptr = POINTER(LinuxDirent64)
    
    libc_dll = this_process = CDLL(None, use_errno=True)
    # ALWAYS set argtypes and restype for functions, otherwise it's UB!!!
    opendir = libc_dll.opendir
    readdir = libc_dll.readdir
    closedir = libc_dll.closedir
    
    
    def get_dir_content(path):
        ret = [path, list(), list()]
        dir_stream = opendir(create_string_buffer(path.encode()))
        if (dir_stream == 0):
            print("opendir returned NULL (errno: {:d})".format(get_errno()))
            return ret
        set_errno(0)
        dirent_addr = readdir(dir_stream)
        while dirent_addr:
            dirent_ptr = cast(dirent_addr, LinuxDirent64Ptr)
            dirent = dirent_ptr.contents
            name = dirent.d_name.decode()
            if dirent.d_type & DT_DIR:
                if name not in (".", ".."):
                    ret[1].append(name)
            Elif dirent.d_type & DT_REG:
                ret[2].append(name)
            dirent_addr = readdir(dir_stream)
        if get_errno():
            print("readdir returned NULL (errno: {:d})".format(get_errno()))
        closedir(dir_stream)
        return ret
    
    
    def main():
        print("{:s} on {:s}\n".format(sys.version, sys.platform))
        root_dir = "root_dir"
        entries = get_dir_content(root_dir)
        print(entries)
    
    
    if __== "__main__":
        main()
    

    Notizen:

    • Es lädt die drei Funktionen aus libc (im aktuellen Prozess geladen) und ruft sie auf (für weitere Details check [SO]: Wie überprüfe ich, ob eine Datei vorhanden ist Existiert ausnahmslos? (@ CristiFatis Antwort) - Letzte Notizen von Punkt # 4. ). Dies würde diesen Ansatz sehr nahe an den Rand von Python / [~ # ~] c [~ # ~] bringen
    • LinuxDirent64 ist die ctypes Darstellung von struct dirent64 von [man7]: dirent.h (0P) (also sind die DT _ Konstanten) von meinem Computer: Ubtu 16 x64 ( 4.10.0-40-generic und libc6-dev: AMD64 ). In anderen Versionen kann die Strukturdefinition abweichen. In diesem Fall sollte der Alias ​​ ctypes aktualisiert werden, da er sonst ndefiniertes Verhalten ergibt
    • Es werden Daten im Format os.walk Zurückgegeben. Ich habe mich nicht darum gekümmert, es rekursiv zu machen, aber mit dem vorhandenen Code zu beginnen, wäre eine ziemlich triviale Aufgabe
    • Alles ist machbar auf Win , auch die Daten (Bibliotheken, Funktionen, Strukturen, Konstanten, ...) unterscheiden sich


    Ausgabe:

    [[email protected]:~/Work/Dev/StackOverflow/q003207219]> ./code_ctypes.py
    3.5.2 (default, Nov 12 2018, 13:43:14)
    [GCC 5.4.0 20160609] on linux
    
    ['root_dir', ['dir2', 'dir1', 'dir3', 'dir0'], ['file1', 'file0']]
    


  1. [ActiveState.Docs]: win32file.FindFilesW ( Win spezifisch)

    Ruft mithilfe der Windows Unicode-API eine Liste übereinstimmender Dateinamen ab. Eine Schnittstelle zur API FindFirstFileW/FindNextFileW/Find close Funktionen.


    >>> import os, win32file, win32con
    >>> root_dir = "root_dir"
    >>> wildcard = "*"
    >>> root_dir_wildcard = os.path.join(root_dir, wildcard)
    >>> entry_list = win32file.FindFilesW(root_dir_wildcard)
    >>> len(entry_list)  # Don't display the whole content as it's too long
    8
    >>> [entry[-2] for entry in entry_list]  # Only display the entry names
    ['.', '..', 'dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [entry[-2] for entry in entry_list if entry[0] & win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2] not in (".", "..")]  # Filter entries and only display dir names (except self and parent)
    ['dir0', 'dir1', 'dir2', 'dir3']
    >>>
    >>> [os.path.join(root_dir, entry[-2]) for entry in entry_list if entry[0] & (win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)]  # Only display file "full" names
    ['root_dir\\file0', 'root_dir\\file1']
    

    Notizen:


  1. Installieren Sie ein (anderes) Drittanbieterpaket, das den Trick macht
    • Wird sich höchstwahrscheinlich auf eines (oder mehrere) der oben genannten Elemente stützen (möglicherweise mit geringfügigen Anpassungen)


Notizen:

  • Der Code muss tragbar sein (mit Ausnahme von Orten, die auf einen bestimmten Bereich abzielen - die markiert sind) oder Folgendes umfassen:

    • plattform ( Nix , Win ,)
    • Python Version (2, 3,)
  • In den obigen Varianten wurden mehrere Pfadstile (absolut, relativ) verwendet, um die Tatsache zu veranschaulichen, dass die verwendeten "Werkzeuge" in dieser Richtung flexibel sind

  • os.listdir Und os.scandir Verwenden opendir / readdir / closedir ( [MS.Docs]: FindFirstFileW-Funktion / [MS.Docs]: FindNextFileW-Funktion / [ MS.Docs]: FindClose-Funktion (via [GitHub]: python/cpython - (master) cpython/Modules/posixmodule.c )

  • win32file.FindFilesW Verwendet auch diese ( Win spezifischen) Funktionen (über [GitHub]: mhammond/pywin32 - (master) pywin32/win32/src /win32file.i )

  • _ get_dir_content (from point # 1. ) kann mit jedem dieser Ansätze implementiert werden (einige werden es tun) erfordern mehr Arbeit und einige weniger)

    • Einige erweiterte Filter (anstelle von nur file vs. dir) könnten durchgeführt werden: z. Das Argument include_folders könnte durch ein anderes ersetzt werden (z. B. filter_func ). Dies wäre eine Funktion, die einen Pfad als Argument verwendet: filter_func=lambda x: True (Dies entfernt nichts) und innerhalb von _ get_dir_content so etwas wie: if not filter_func(entry_with_path): continue (wenn die Funktion für einen Eintrag fehlschlägt, ist es wird übersprungen), aber je komplexer der Code wird, desto länger dauert die Ausführung
  • Nota bene! Da die Rekursion verwendet wird, muss ich erwähnen, dass ich einige Tests auf meinem Laptop durchgeführt habe ( Win 10 x64 ), die absolut nichts mit diesem Problem zu tun haben. und wenn die Rekursionsstufe Werte irgendwo im Bereich (990 .. 1000) erreichte ( recursionlimit - 1000 (Standard)) Habe ich StackOverflow :). Wenn der Verzeichnisbaum diese Grenze überschreitet (ich bin kein [~ # ~] fs [~ # ~] Experte, also weiß ich nicht, ob das überhaupt möglich ist), das könnte ein problem sein.
    Ich muss auch erwähnen, dass ich nicht versucht habe, recursionlimit zu erhöhen, weil ich keine Erfahrung in diesem Bereich habe (wie viel kann ich erhöhen, bevor ich auch erhöhen muss) der Stack auf [~ # ~] os [~ # ~] level), theoretisch besteht jedoch immer die Möglichkeit eines Ausfalls, wenn die dir-Tiefe größer als die höchste ist möglich recursionlimit (auf diesem Rechner)

  • Die Codebeispiele dienen nur zu Demonstrationszwecken. Das bedeutet, dass ich die Fehlerbehandlung nicht berücksichtigt habe (ich glaube nicht, dass es try /) gibt + außer / else / finally block), daher ist der Code nicht robust (der Grund dafür ist, ihn so einfach und kurz wie möglich zu halten). Für production sollte auch eine Fehlerbehandlung hinzugefügt werden

Andere Ansätze:

  1. Verwenden Sie Python nur als Wrapper

    • Alles wird mit einer anderen Technologie gemacht
    • Diese Technologie wird von Python aufgerufen
    • Die bekannteste Variante, die ich kenne, ist das, was ich Systemadministrator nenne:

      • Verwenden Sie Python (oder eine andere Programmiersprache), um Shell Befehle auszuführen (und deren Ausgaben zu analysieren)
      • Einige halten dies für einen ordentlichen Hack
      • Ich betrachte es eher als lahmen Workaround ( gainarie ), da die Aktion per se von Shell ( cmd in diesem Fall) und hat daher nichts mit Python zu tun.
      • Filterung (grep/findstr) oder Ausgabeformatierung können auf beiden Seiten durchgeführt werden, aber ich werde nicht darauf bestehen. Außerdem habe ich absichtlich os.system Anstelle von subprocess.Popen Verwendet.
      (py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")"
      dir0
      dir1
      dir2
      dir3
      file0
      file1
      

    Im Allgemeinen sollte dieser Ansatz vermieden werden, da der Parsing-Code verwendet werden sollte, wenn sich ein Befehlsausgabeformat zwischen den Versionen/Varianten von [~ # ~] os [~ # ~] geringfügig unterscheidet auch angepasst; nicht zu erwähnen, Unterschiede zwischen den Standorten).

52
CristiFati

Ich mochte Adams Antwort und schlug vor, dass Sie glob() aus dem Modul mit dem gleichen Namen verwenden. Auf diese Weise können Sie Muster mit *s abgleichen.

Aber wie andere in den Kommentaren darauf hingewiesen haben, kann glob() über inkonsistente Schrägstriche stolpern. Als Hilfe schlage ich vor, dass Sie die Funktionen join() und expanduser() im Modul os.path und möglicherweise die Funktion getcwd() im Modul os als verwenden Gut.

Als Beispiele:

from glob import glob

# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')

Das Obige ist furchtbar - der Pfad wurde fest codiert und funktioniert unter Windows nur zwischen dem Laufwerksnamen und den \s, die fest in den Pfad codiert sind.

from glob    import glob
from os.path import join

# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users', 'admin', '*', 'wlp'))

Das oben Genannte funktioniert besser, aber es basiert auf dem Ordnernamen Users, der häufig unter Windows und nicht so häufig unter anderen Betriebssystemen verwendet wird. Es hängt auch davon ab, dass der Benutzer einen bestimmten Namen hat, admin.

from glob    import glob
from os.path import expanduser, join

# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'), '*', 'wlp'))

Dies funktioniert perfekt auf allen Plattformen.

Ein weiteres großartiges Beispiel, das plattformübergreifend perfekt funktioniert und etwas anderes macht:

from glob    import glob
from os      import getcwd
from os.path import join

# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(), '*', 'wlp'))

Ich hoffe, diese Beispiele helfen Ihnen dabei, die Leistungsfähigkeit einiger Funktionen zu erkennen, die Sie in den Standardbibliotheksmodulen Python finden.

47
ArtOfWarfare
def list_files(path):
    # returns a list of names (with extension, without full path) of all files 
    # in folder path
    files = []
    for name in os.listdir(path):
        if os.path.isfile(os.path.join(path, name)):
            files.append(name)
    return files 
34
Apogentus

Wenn Sie nach einer Python -Implementierung von find suchen, ist dies ein Rezept, das ich ziemlich häufig verwende:

from findtools.find_files import (find_files, Match)

# Recursively find all *.sh files in **/usr/bin**
sh_files_pattern = Match(filetype='f', name='*.sh')
found_files = find_files(path='/usr/bin', match=sh_files_pattern)

for found_file in found_files:
    print found_file

Also habe ich ein PyPI Paket daraus gemacht und es gibt auch ein GitHub Repository . Ich hoffe, dass jemand es für diesen Code möglicherweise nützlich findet.

22

Das Zurückgeben einer Liste absoluter Dateipfade führt nicht zu Unterverzeichnissen

L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]
11
The2ndSon

Um bessere Ergebnisse zu erzielen, können Sie die listdir() -Methode des os -Moduls zusammen mit einem Generator verwenden (ein Generator ist ein leistungsfähiger Iterator, der seinen Zustand beibehält. Erinnern Sie sich?). Der folgende Code funktioniert in beiden Versionen einwandfrei: Python 2 und Python 3.

Hier ist ein Code:

import os

def files(path):  
    for file in os.listdir(path):
        if os.path.isfile(os.path.join(path, file)):
            yield file

for file in files("."):  
    print (file)

Die Methode listdir() gibt die Liste der Einträge für das angegebene Verzeichnis zurück. Die Methode os.path.isfile() gibt True zurück, wenn der angegebene Eintrag eine Datei ist. Der Operator yield beendet die Funktion, behält jedoch ihren aktuellen Status bei und gibt nur den Namen des als Datei erkannten Eintrags zurück. All dies ermöglicht es uns, die Generatorfunktion zu durchlaufen.

10
ARGeo
import os
import os.path


def get_files(target_dir):
    item_list = os.listdir(target_dir)

    file_list = list()
    for item in item_list:
        item_dir = os.path.join(target_dir,item)
        if os.path.isdir(item_dir):
            file_list += get_files(item_dir)
        else:
            file_list.append(item_dir)
    return file_list

Hier verwende ich eine rekursive Struktur.

9
pah8J

Ich gehe davon aus, dass alle Ihre Dateien das Format *.txt haben und in einem Verzeichnis mit dem Pfad data/ gespeichert sind.

Man kann das glob Modul von python verwenden, um alle Dateien des Verzeichnisses aufzulisten und sie einer Liste mit dem Namen fnames auf folgende Weise hinzuzufügen:

import glob

fnames = glob.glob("data/*.txt")  #fnames: list data type
9

Ein weiser Lehrer sagte mir einmal:

Wenn es mehrere bewährte Methoden gibt, ist keine für alle Fälle geeignet.

Ich füge daher eine Lösung für eine Teilmenge des Problems hinzu: Wir wollen häufig nur prüfen, ob eine Datei mit einer Start- und einer Endzeichenfolge übereinstimmt, ohne in Unterverzeichnisse zu wechseln. Wir möchten daher eine Funktion, die eine Liste von Dateinamen zurückgibt, wie:

filenames = dir_filter('foo/baz', radical='radical', extension='.txt')

Wenn Sie zuerst zwei Funktionen deklarieren möchten, können Sie dies tun:

def file_filter(filename, radical='', extension=''):
    "Check if a filename matches a radical and extension"
    if not filename:
        return False
    filename = filename.strip()
    return(filename.startswith(radical) and filename.endswith(extension))

def dir_filter(dirname='', radical='', extension=''):
    "Filter filenames in directory according to radical and extension"
    if not dirname:
        dirname = '.'
    return [filename for filename in os.listdir(dirname)
                if file_filter(filename, radical, extension)]

Diese Lösung kann leicht mit regulären Ausdrücken verallgemeinert werden (und Sie können ein pattern-Argument hinzufügen, wenn Ihre Muster nicht immer am Anfang oder Ende des Dateinamens bleiben sollen).

6
fralau

Generatoren verwenden

import os
def get_files(search_path):
     for (dirpath, _, filenames) in os.walk(search_path):
         for filename in filenames:
             yield os.path.join(dirpath, filename)
list_files = get_files('.')
for filename in list_files:
    print(filename)
5
shantanoo

Sie können diesen Code verwenden, um einen Iterator zu erhalten, der über den gesamten Pfad der Dateien (Verzeichnisse + Dateiname) ausgeführt wird.

import os

def get_iterator_all_files_name(dir_path):
    for (dirpath, dirnames, filenames) in os.walk(dir_path):
        for f in filenames:
            yield os.path.join(dirpath, f)

Oder benutze das, um es in die Liste aufzunehmen.

import os

def get_list_all_files_name(dir_path):
    all_files_path = []

    for (dirpath, dirnames, filenames) in os.walk(dir_path):
        for f in filenames:
            all_files_path.append(os.path.join(dirpath, f))

    return all_files_path
5
yehuda corsia
# -** coding: utf-8 -*-
import os
import traceback

print '\n\n'

def start():
    address = "/home/ubuntu/Desktop"
    try:
        Folders = []
        Id = 1
        for item in os.listdir(address):
            endaddress = address + "/" + item
            Folders.append({'Id': Id, 'TopId': 0, 'Name': item, 'Address': endaddress })
            Id += 1         

            state = 0
            for item2 in os.listdir(endaddress):
                state = 1
            if state == 1: 
                Id = FolderToList(endaddress, Id, Id - 1, Folders)
        return Folders
    except:
        print "___________________________ ERROR ___________________________\n" + traceback.format_exc()

def FolderToList(address, Id, TopId, Folders):
    for item in os.listdir(address):
        endaddress = address + "/" + item
        Folders.append({'Id': Id, 'TopId': TopId, 'Name': item, 'Address': endaddress })
        Id += 1

        state = 0
        for item in os.listdir(endaddress):
            state = 1
        if state == 1: 
            Id = FolderToList(endaddress, Id, Id - 1, Folders)
    return Id

print start()
5
barisim.net

Verwenden Sie diese Funktion, wenn Sie einen anderen Dateityp verwenden oder das vollständige Verzeichnis abrufen möchten:

import os

def createList(foldername, fulldir = True, suffix=".jpg"):
    file_list_tmp = os.listdir(foldername)
    #print len(file_list_tmp)
    file_list = []
    if fulldir:
        for item in file_list_tmp:
            if item.endswith(suffix):
                file_list.append(os.path.join(foldername, item))
    else:
        for item in file_list_tmp:
            if item.endswith(suffix):
                file_list.append(item)
    return file_list
3
neouyghur

Eine andere gut lesbare Variante für Python 3.4+ verwendet pathlib.Path.glob:

from pathlib import Path
folder = '/foo'
[f for f in Path(folder).glob('*') if f.is_file()]

Es ist einfach, spezifischer zu machen, z.B. Suche nur nach Python Quelldateien, die keine symbolischen Links sind, auch in allen Unterverzeichnissen:

[f for f in Path(folder).glob('**/*.py') if not f.is_symlink()]
3
fhchl

dircache ist "Veraltet seit Version 2.6: Das dircache-Modul wurde in Python 3.0 entfernt."

import dircache
list = dircache.listdir(pathname)
i = 0
check = len(list[0])
temp = []
count = len(list)
while count != 0:
  if len(list[i]) != check:
     temp.append(list[i-1])
     check = len(list[i])
  else:
    i = i + 1
    count = count - 1

print temp
2
shaji

Hier ist meine Allzweckfunktion dafür. Es gibt eine Liste der Dateipfade anstatt der Dateinamen zurück, da ich dies für nützlicher hielt. Es hat ein paar optionale Argumente, die es vielseitig machen. Zum Beispiel benutze ich es oft mit Argumenten wie pattern='*.txt' oder subfolders=True.

import os
import fnmatch

def list_paths(folder='.', pattern='*', case_sensitive=False, subfolders=False):
    """Return a list of the file paths matching the pattern in the specified 
    folder, optionally including files inside subfolders.
    """
    match = fnmatch.fnmatchcase if case_sensitive else fnmatch.fnmatch
    walked = os.walk(folder) if subfolders else [next(os.walk(folder))]
    return [os.path.join(root, f)
            for root, dirnames, filenames in walked
            for f in filenames if match(f, pattern)]
2
MarredCheese

Für python2: pip installiere rglob

import rglob
file_list=rglob.rglob("/home/base/dir/", "*")
print file_list
1
chris-piekarski

Ich werde ein Beispiel eines Liners bereitstellen, in dem Quellpfad und Dateityp als Eingabe bereitgestellt werden können. Der Code gibt eine Liste der Dateinamen mit der Erweiterung csv zurück. Verwenden Sie ., wenn alle Dateien zurückgegeben werden müssen. Dadurch werden auch die Unterverzeichnisse rekursiv durchsucht.

[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]

Ändern Sie die Dateierweiterungen und den Quellpfad nach Bedarf.

0