os.listdir()Sie erhalten alles, was sich in einem Verzeichnis befindet - Dateien und Verzeichnisse .
Wenn Sie nur Dateien möchten , können Sie diese entweder nach unten filtern os.path:
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 verwenden, os.walk()was zwei Listen für jedes Verzeichnis ergibt, das es besucht - Aufteilen in Dateien und Verzeichnisse für Sie. Wenn Sie nur das oberste Verzeichnis wollen, können Sie es einfach beim ersten Mal brechen
from os import walk
f =[]for(dirpath, dirnames, filenames)in walk(mypath):
f.extend(filenames)break
Ein bisschen einfacher: (_, _, filenames) = walk(mypath).next() (wenn Sie sicher sind, dass der Spaziergang mindestens einen Wert
zurückgibt
9
Leichte Änderung zum Speichern vollständiger Pfade: für (dirpath, dirnames, filenames) in os.walk (mypath): testsum_files.extend (os.path.join (dirpath, filename) für filename in filenames) break
okigan
150
f.extend(filenames)ist eigentlich nicht gleichbedeutend mit f = f + filenames. extendwird fan Ort und Stelle geändert, während durch Hinzufügen eine neue Liste an einem neuen Speicherort erstellt wird. Dies bedeutet extendim Allgemeinen effizienter als +, kann jedoch manchmal zu Verwirrung führen, wenn mehrere Objekte Verweise auf die Liste enthalten. Schließlich ist es erwähnenswert, dass f += filenamesdies nicht gleichbedeutend f.extend(filenames)ist . f = f + filenames
Benjamin Hodgson
30
@misterbee, Ihre Lösung ist die beste, nur eine kleine Verbesserung:_, _, filenames = next(walk(mypath), (None, None, []))
Bgusach
35
in Python 3.x verwenden(_, _, filenames) = next(os.walk(mypath))
ET-CS
1683
Ich bevorzuge die Verwendung des globModuls, da es Mustervergleich und -erweiterung durchführt.
import glob
print(glob.glob("/home/adam/*.txt"))
Es wird eine Liste mit den abgefragten Dateien zurückgegeben:
Zur Verdeutlichung gibt dies nicht den "vollständigen Pfad" zurück. es gibt einfach die Expansion des Glob zurück, was auch immer es sein mag. Beispiel gegeben /home/user/foo/bar/hello.txt, dann, wenn im Verzeichnis ausgeführt wird foo, die glob("bar/*.txt")angezeigt werden kann bar/hello.txt. Es gibt Fälle, in denen Sie tatsächlich den vollständigen (dh absoluten) Pfad möchten. Für diese Fälle siehe stackoverflow.com/questions/51520/…
beantwortet diese Frage nicht. glob.glob("*")würde.
Jean-François Fabre
wunderschönen!!!! Also ... x=glob.glob("../train/*.png")werde mir eine Reihe meiner Pfade geben, solange ich den Namen des Ordners kenne. So cool!
Jennifer Crosby
858
Holen Sie sich eine Liste der Dateien mit Python 2 und 3
os.listdir()
So erhalten Sie alle Dateien (und Verzeichnisse) im aktuellen Verzeichnis (Python 3)
Im Folgenden finden Sie einfache Methoden zum Abrufen nur von Dateien im aktuellen Verzeichnis mithilfe von os und der listdir()Funktion in Python 3. Weitere Untersuchungen zeigen, wie Ordner im Verzeichnis zurückgegeben werden. Sie haben die Datei jedoch nicht im Unterverzeichnis kann zu Fuß gehen (später besprochen).
import os
arr = os.listdir()print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
glob
Ich fand glob einfacher, die Datei des gleichen 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
Die Funktion gibt eine Liste der angegebenen Erweiterung (.txt, .docx ecc.) Im Argument zurück
import glob
def filebrowser(ext=""):"Returns files with an extension"return[f for f in glob.glob(f"*{ext}")]
x = filebrowser(".txt")print(x)>>>['example.txt','fb.txt','intro.txt','help.txt']
glob Erweiterung des vorherigen Codes
Die Funktion gibt jetzt eine Liste der Dateien zurück, die mit der Zeichenfolge übereinstimmen, die Sie als Argument übergeben
import glob
def filesearch(word=""):"""Returns a list with all files with the word/extension in it"""
file =[]for f in glob.glob("*"):if word[0]==".":if f.endswith(word):
file.append(f)return file
elif word in f:
file.append(f)return file
return file
lookfor ="example",".py"for w in lookfor:print(f"{w:10} found => {filesearch(w)}")
Ausgabe
example found =>[].py found =>['search.py']
Den vollständigen Pfadnamen mit abrufen os.path.abspath
Wie Sie bemerkt haben, haben Sie im obigen Code nicht den vollständigen Pfad der Datei. Wenn Sie den absoluten Pfad benötigen, können Sie eine andere Funktion des os.pathaufgerufenen Moduls verwenden _getfullpathnameund die Datei, aus der Sie sie erhalten, os.listdir()als Argument verwenden. Es gibt andere Möglichkeiten, den vollständigen Pfad zu erhalten, wie wir später überprüfen werden (ich habe, wie von mexmex vorgeschlagen, _getfullpathname durch ersetzt abspath).
import os
files_path =[os.path.abspath(x)for x in os.listdir()]print(files_path)>>>['F:\\documenti\applications.txt','F:\\documenti\collections.txt']
Holen Sie sich den vollständigen Pfadnamen eines Dateityps in alle Unterverzeichnisse mit walk
Ich finde das sehr nützlich, um Dinge in vielen Verzeichnissen zu finden, und es hat mir geholfen, eine Datei zu finden, an die ich mich nicht erinnern konnte:
import os
# Getting the current work directory (cwd)
thisdir = os.getcwd()# r=root, d=directories, f = filesfor r, d, f in os.walk(thisdir):for file in f:if file.endswith(".docx"):print(os.path.join(r, file))
os.listdir(): Dateien im aktuellen Verzeichnis abrufen (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']
In den Verzeichnisbaum aufsteigen
# 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']
Holen Sie sich 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 den vollständigen Pfad - Listenverständnis
[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 - Vollständigen Pfad abrufen - 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() - Holen Sie sich nur TXT-Dateien
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 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 pathlibvon 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()]
Alternativ können Sie pathlib.Path()anstelle von verwendenpathlib.Path(".")
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() ab 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 suchen wir nach der Anzahl der Dateien, 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 +=1return 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, mit dem Sie auf Ihrem Computer alle Dateien eines Typs (Standard: pptx) suchen und in einen neuen Ordner kopieren können.
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 +=1if 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
>>>------------------------>>>==>Foundin:`_compiti18`:3 files
Ex. 3: So erhalten Sie 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")
Die gesamte Datei 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 von einer anderen Position aus starten müssen. Dieser Code generiert eine 50-MB-Textdatei auf meinem Computer mit 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
(Neu) Finde alle Dateien und öffne sie mit der tkinter GUI
Ich wollte in diesem Jahr 2019 nur eine kleine App hinzufügen, um nach allen Dateien in einem Verzeichnis zu suchen und sie durch Doppelklicken auf den Namen der Datei in der Liste öffnen zu können.
import tkinter as tk
import os
def searchfiles(extension='.txt', folder='H:\\'):"insert all files in the listbox"for r, d, f in os.walk(folder):for file in f:if file.endswith(extension):
lb.insert(0, r +"\\"+ file)def open_file():
os.startfile(lb.get(lb.curselection()[0]))
root = tk.Tk()
root.geometry("400x400")
bt = tk.Button(root, text="Search", command=lambda:searchfiles('.png','H:\\'))
bt.pack()
lb = tk.Listbox(root)
lb.pack(fill="both", expand=1)
lb.bind("<Double-Button>",lambda x: open_file())
root.mainloop()
Dies ist eine Mischung aus zu vielen Antworten auf Fragen, die hier nicht gestellt werden. Es kann auch sinnvoll sein, die Vorbehalte oder empfohlenen Ansätze zu erläutern. Ich bin nicht besser dran, einen Weg zu kennen als 20 Wege, um dasselbe zu tun, es sei denn, ich weiß auch, welcher Zeitpunkt besser geeignet ist.
cs95
Ok, so schnell wie möglich werde ich mir meine Antwort ansehen und versuchen, sie sauberer und mit nützlicheren Informationen über den Unterschied zwischen den Methoden usw. zu gestalten.
Giovanni G. PY
Sie sollten die Dateierweiterung nicht ermitteln, indem Sie überprüfen, ob der Dateiname eine Teilzeichenfolge enthält. Das könnte viele Probleme verursachen. Ich empfehle immer zu überprüfen, ob der Dateiname mit dem jeweiligen Teilstring endet.
ni1ight
Ok, @ n1light Ich habe den Code geändert ...
Giovanni G. PY
811
import os
os.listdir("somedirectory")
gibt eine Liste aller Dateien und Verzeichnisse in "somedirectory" zurück.
Dies gibt den relativen Pfad der Dateien zurück, verglichen mit dem vollständigen Pfad, der vonglob.glob
xji
22
@JIXiang: Gibt os.listdir()immer nur Dateinamen zurück (keine relativen Pfade). Was glob.glob()zurückkehrt, hängt vom Pfadformat des Eingabemusters ab.
mklement0
os.listdir () -> Es werden immer das Verzeichnis und die Datei am angegebenen Speicherort aufgelistet. Gibt es eine Möglichkeit, nur Verzeichnisse und keine Dateien aufzulisten?
RonyA
160
Eine einzeilige Lösung, um nur eine Liste von Dateien (keine Unterverzeichnisse) abzurufen:
filenames = next(os.walk(path))[2]
oder absolute Pfadnamen:
paths =[os.path.join(path, fn)for fn in next(os.walk(path))[2]]
Nur ein Einzeiler, wenn Sie bereits haben import os. Scheint weniger prägnant als glob()für mich.
ArtOfWarfare
4
Problem mit glob ist, dass ein Ordner mit dem Namen 'Something.something' von glob ('/ home / adam /*.*') zurückgegeben wird
Remi
6
Unter OS X gibt es ein sogenanntes Bundle. Es ist ein Verzeichnis, das im Allgemeinen als Datei behandelt werden sollte (wie eine .tar). Möchten Sie, dass diese als Datei oder Verzeichnis behandelt werden? Die Verwendung glob()würde es als Datei behandeln. Ihre Methode würde es als Verzeichnis behandeln.
ArtOfWarfare
132
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 Dinge tun wie:
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 beschrieben:
for f in full_file_paths:if f.endswith(".dat"):print f
>>>import pathlib
>>>[p for p in pathlib.Path('.').iterdir()if p.is_file()]
Gemäß PEP 428 besteht das Ziel der pathlibBibliothek darin, eine einfache Hierarchie von Klassen bereitzustellen, um Dateisystempfade und die allgemeinen Operationen, die Benutzer über sie ausführen, zu handhaben.
Vielen Dank! Ich denke, es ist die einzige Lösung, die nicht direkt zurückkehrt list. Könnte alternativ p.nameanstelle der ersten verwendet werden, pwenn dies bevorzugt wird.
Jeromej
1
Herzlich willkommen! Ich würde es vorziehen zu generierenpathlib.Path() Instanzen zu da sie viele nützliche Methoden haben, mit denen ich keinen Abfall verschwenden möchte. Sie können str(p)sie auch für Pfadnamen aufrufen .
SzieberthAdam
6
Hinweis: Die os.scandirLösung ist effizienter als os.listdirbei einer os.path.is_filePrüfung oder Ähnlichem, selbst wenn Sie eine benötigen list(damit Sie nicht von einer verzögerten Iteration profitieren), da os.scandirvom Betriebssystem bereitgestellte APIs verwendet werden, mit denen Sie die is_fileInformationen während der Iteration kostenlos erhalten , überhaupt kein Roundtrip pro Datei auf die Festplatte zu statihnen (unter Windows DirEntryerhalten Sie statkostenlos vollständige Informationen, auf * NIX-Systemen, die statfür weitere Informationen erforderlich sindis_file , is_dirusw., aber DirEntryCaches auf den ersten der statEinfachheit halber).
ShadowRanger
1
Sie können auch verwenden entry.name nur den Dateinamen oder entry.pathden vollständigen Pfad abrufen. Nicht mehr überall os.path.join ().
user136036
56
Vorbemerkungen
Obwohl es im Fragetext eine klare Unterscheidung zwischen Datei- und Verzeichnisbegriffen gibt , können einige argumentieren, dass Verzeichnisse tatsächlich spezielle Dateien sind
Die Anweisung " Alle Dateien eines Verzeichnisses " kann auf zwei Arten interpretiert werden:
Nur alle direkten (oder Level 1) Nachkommen
Alle Nachkommen im gesamten Verzeichnisbaum (einschließlich derjenigen in Unterverzeichnissen)
Als die Frage gestellt wurde, stelle ich mir vor, dass Python 2 die LTS- Version war, die Codebeispiele werden jedoch von Python 3 ( .5 ) ausgeführt (ich werde sie so Python 2- konform wie möglich halten; auch jeden dazugehörigen Code Python , das ich veröffentlichen werde, stammt aus Version 3.5.4 (sofern nicht anders angegeben). Dies hat Konsequenzen im Zusammenhang mit einem anderen Schlüsselwort in der Frage: " Fügen Sie sie einer Liste hinzu ":
In Versionen vor Python 2.2 wurden Sequenzen (Iterables) hauptsächlich durch Listen (Tupel, Mengen, ...) dargestellt.
In Python 2.2 ist das Konzept von Generators ( [Python.Wiki]: Generators ) - mit freundlicher Genehmigung von [Python 3]: The Yield Statement ) eingeführt. Im Laufe der Zeit wurden Generator-Gegenstücke für Funktionen angezeigt, die Listen zurückgaben / mit ihnen arbeiteten
In Python 3 ist der Generator das Standardverhalten
Sie sind sich nicht sicher, ob die Rückgabe einer Liste weiterhin obligatorisch ist (oder auch ein Generator), aber wenn Sie einen Generator an den Listenkonstruktor übergeben , wird daraus eine Liste erstellt (und auch verbraucht). Das folgende Beispiel zeigt die Unterschiede in [Python 3]: map ( Funktion, iterierbar, ... )
>>>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 denselben Baum auch auf Lnx ):
Gibt eine Liste mit den Namen der Einträge in dem durch path angegebenen Verzeichnis zurück. Die Liste ist in beliebiger Reihenfolge und enthält keine 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 __name__ =="__main__":
main()
Anmerkungen :
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 klassische (Funktionsnamen, die auf _old enden )
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
Der öffentliche (Wrapper gegenüber dem vorherigen): Er 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 dieser Stelle kommen könnte
In Bezug auf die Leistung sind Generatoren im Allgemeinen etwas schneller (sowohl unter Berücksichtigung der Erstellungs- als auch der Iterationszeiten ), aber ich habe sie nicht in rekursiven Funktionen getestet und iteriere auch innerhalb der Funktion über innere Generatoren - ich weiß nicht, wie die Leistung ist freundlich ist das
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']
Gibt einen Iterator von os.DirEntry- Objekten zurück, der den Einträgen in dem durch path angegebenen Verzeichnis entspricht . Die Einträge werden in beliebiger Reihenfolge und die speziellen Einträge ausgegeben '.'und '..'sind nicht enthalten.
Die Verwendung von scandir () anstelle von listdir () kann die Leistung von Code, der auch Dateityp- oder Dateiattributinformationen benötigt, erheblich verbessern , da os.DirEntry- Objekte diese Informationen verfügbar machen , wenn das Betriebssystem sie beim Scannen eines Verzeichnisses bereitstellt. Alle os.DirEntry- Methoden führen möglicherweise einen Systemaufruf aus, aber is_dir () und is_file () erfordern normalerweise nur einen Systemaufruf für symbolische Links. os.DirEntry.stat () erfordert unter Unix immer einen Systemaufruf, unter Windows jedoch nur einen für symbolische Links.
>>>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
Anmerkungen :
Es ist ähnlich wie os.listdir
Es ist aber auch flexibler (und bietet mehr Funktionalität), mehr Python- IC (und in einigen Fällen schneller)
Generieren Sie die Dateinamen in einem Verzeichnisbaum, indem Sie den Baum entweder von oben nach unten oder von unten nach oben durchlaufen. Für jedes Verzeichnis in dem Verzeichnisbaum am wurzelt oben (einschließlich der oben selbst), es ergibt sich 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',[],[])
Anmerkungen :
Unter den Kulissen wird es verwendet os.scandir( os.listdirbei älteren Versionen)
Es erledigt das schwere Heben, indem es in Unterordnern wiederholt wird
Gibt eine möglicherweise leere Liste von Pfadnamen zurück , die mit dem Pfadnamen übereinstimmen. Dies muss eine Zeichenfolge sein, die eine Pfadspezifikation enthält. Der Pfadname kann entweder absolut (wie /usr/src/Python-1.5/Makefile) oder relativ (wie ../../Tools/*/*.gif) sein und Platzhalter im Shell-Stil enthalten. Unterbrochene 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
Anmerkungen :
Verwendet os.listdir
Bei großen Bäumen (insbesondere wenn rekursiv aktiviert ist ) wird Iglob bevorzugt
Ermöglicht erweiterte Filterung basierend auf dem Namen (aufgrund des Platzhalters)
>>>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("*")ifnot item.is_dir()]# Display paths (including parent) for files only['root_dir\\file0','root_dir\\file1']
Anmerkungen :
Dies ist ein Weg, um unser Ziel zu erreichen
Es ist der OOP- Stil für die Behandlung von Pfaden
def listdir(path):"""List directory contents, using cache."""try:
cached_mtime, list = cache[path]del cache[path]exceptKeyError:
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
ctypes ist eine Fremdfunktionsbibliothek 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 reines Python zu verpacken.
LinuxDirent64 ist die ctypes- Darstellung von struct dirent64 aus [man7]: dirent.h (0P) (ebenso wie die DT_- Konstanten) von meinem Computer: Ubtu 16 x64 ( 4.10.0-40-generic und libc6-dev: amd64 ). Bei anderen Varianten / Versionen kann die Strukturdefinition abweichen. In diesem Fall sollte der Alias ctypes aktualisiert werden, da sonst undefiniertes Verhalten angezeigt wird
Es gibt Daten im os.walkFormat zurück. Ich habe mich nicht darum gekümmert, es rekursiv zu machen, aber ausgehend vom vorhandenen Code wäre das eine ziemlich triviale Aufgabe
Auch unter Win ist alles machbar , die Daten (Bibliotheken, Funktionen, Strukturen, Konstanten, ...) unterscheiden sich
Ausgabe :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q003207219]>./code_ctypes.py
3.5.2(default,Nov122018,13:43:14)[GCC 5.4.020160609] on linux
['root_dir',['dir2','dir1','dir3','dir0'],['file1','file0']]
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 long8>>>[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]notin(".","..")]# 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']
Der Dokumentationslink stammt von ActiveState , da ich keine offizielle PyWin32- Dokumentation gefunden habe
Installieren Sie ein (anderes) Paket eines Drittanbieters, das den Trick ausführt
Wird sich höchstwahrscheinlich auf eine (oder mehrere) der oben genannten Methoden stützen (möglicherweise mit geringfügigen Anpassungen).
Anmerkungen :
Der Code soll tragbar (mit Ausnahme von Orten, die auf einen bestimmten Bereich abzielen - die markiert sind) oder kreuzweise sein:
Plattform ( Nix , Win ,)
Python- Version (2, 3,)
In den obigen Varianten wurden mehrere Pfadstile (absolut, Verwandte) verwendet, um die Tatsache zu veranschaulichen, dass die verwendeten "Werkzeuge" in dieser Richtung flexibel sind
_get_dir_content (ab Punkt 1 ) kann mit jedem dieser Ansätze implementiert werden (einige erfordern mehr Arbeit und andere weniger).
Es könnte eine erweiterte Filterung (anstelle von nur Datei vs. Verzeichnis) durchgeführt werden: z. B. könnte das Argument include_folders 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 wird nicht entfernt alles) und in _get_dir_content so etwas wie: if not filter_func(entry_with_path): continue(Wenn die Funktion für einen Eintrag fehlschlägt, wird sie ü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 ( Win 10 x64 ) durchgeführt habe, die völlig unabhängig von diesem Problem waren, und als die Rekursionsstufe Werte irgendwo im Bereich (990 .. 1000) erreichte ( Rekursionslimit - 1000) (Standard)), ich habe StackOverflow :). Wenn der Verzeichnisbaum diese Grenze überschreitet (ich bin kein FS- Experte, daher weiß ich nicht, ob dies überhaupt möglich ist), könnte dies ein Problem sein.
Ich muss auch erwähnen, dass ich nicht versucht habe, das Rekursionslimit zu erhöhen, da ich keine Erfahrung in diesem Bereich habe (wie viel kann ich erhöhen, bevor ich auch den Stack unter OS erhöhen mussLevel), aber theoretisch besteht immer die Möglichkeit eines Ausfalls, wenn die Dir-Tiefe größer ist als das höchstmögliche Rekursionslimit (auf dieser Maschine).
Die Codebeispiele dienen nur zu Demonstrationszwecken. Das bedeutet, dass ich die Fehlerbehandlung nicht berücksichtigt habe (ich glaube, es gibt keinen Versuch / außer / else / finally- Block), daher ist der Code nicht robust (der Grund ist: ihn so einfach und kurz wie möglich zu halten ). Für die Produktion sollte auch die Fehlerbehandlung hinzugefügt werden
Andere Ansätze:
Verwenden Sie Python nur als Wrapper
Alles wird mit einer anderen Technologie erledigt
Diese Technologie wird von Python aufgerufen
Die bekannteste Variante, die ich kenne, ist der sogenannte Systemadministrator- Ansatz:
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 halte es eher wie eine lahme Abhilfe ( gainarie ), da die Aktion an sich aus durchgeführt wird , Shell ( cmd in diesem Fall), und somit nichts mit dem zu tun hat Python .
Das Filtern ( grep/ findstr) oder das Formatieren der Ausgabe könnte auf beiden Seiten erfolgen, aber ich werde nicht darauf bestehen. Auch habe ich absichtlich os.systemstatt subprocess.Popen.
Im Allgemeinen ist dieser Ansatz zu vermeiden, da der Parsing-Code ebenfalls angepasst werden sollte , wenn sich das Befehlsausgabeformat zwischen den Betriebssystemversionen / -varianten geringfügig unterscheidet . ganz zu schweigen von den Unterschieden zwischen den Gebietsschemas).
Ich wirklich mochte adamk Antwort , was darauf hindeutet , dass Sie verwenden glob(), aus dem Modul mit dem gleichen Namen. Auf diese Weise können Sie Muster mit *s abgleichen .
Aber wie andere Leute in den Kommentaren glob()betonten , kann man über inkonsistente Schrägstriche stolpern. Um dies zu unterstützen, schlage ich vor, dass Sie die Funktionen join()und expanduser()im os.pathModul und möglicherweise auch die getcwd()Funktion im osModul verwenden.
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 schrecklich - der Pfad wurde fest codiert und funktioniert unter Windows immer nur zwischen dem Laufwerksnamen und dem \s, das im Pfad fest codiert ist.
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 Obige funktioniert besser, Usershängt jedoch vom Ordnernamen ab, der häufig unter Windows und nicht so häufig unter anderen Betriebssystemen gefunden 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 Standardmodulen der Python-Bibliothek finden.
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
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 möglicherweise nützlich für diesen Code findet.
Für bessere Ergebnisse können Sie die listdir()Methode des osModuls zusammen mit einem Generator verwenden (ein Generator ist ein leistungsstarker Iterator, der seinen Status beibehält, erinnern Sie sich?). Der folgende Code funktioniert mit 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 listdir()Methode gibt die Liste der Einträge für das angegebene Verzeichnis zurück. Die Methode gibt os.path.isfile()zurück, Truewenn der angegebene Eintrag eine Datei ist. Der yieldOperator beendet die Funktion, behält jedoch seinen 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.
Hinweis: os.path.abspath(f)wäre ein etwas billigerer Ersatz für os.path.join(os.getcwd(),f).
ShadowRanger
Ich wäre noch effizienter, wenn Sie damit beginnen cwd = os.path.abspath('.')und dann cwdanstelle von '.'und os.getcwd()durchgehend verwenden würden, um viele redundante Systemaufrufe zu vermeiden.
Das gleiche kann nur in einer Zeile erreicht werden mit pathlib:filter(Path.is_file, Path().rglob('*'))
Georgy
9
Ein weiser Lehrer sagte mir einmal:
Wenn es mehrere etablierte Möglichkeiten gibt, etwas zu tun, ist keine davon für alle Fälle gut.
Ich werde daher eine Lösung für eine Teilmenge des Problems hinzufügen : Oft möchten wir nur prüfen, ob eine Datei mit einer Startzeichenfolge und einer Endzeichenfolge übereinstimmt, ohne in Unterverzeichnisse zu wechseln. Wir möchten daher eine Funktion, die eine Liste von Dateinamen zurückgibt, wie:
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"ifnot filename:returnFalse
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"ifnot 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 möchten möglicherweise ein patternArgument hinzufügen , wenn Ihre Muster nicht immer am Anfang oder Ende des Dateinamens bleiben sollen).
Hier ist meine Allzweckfunktion dafür. Es gibt eine Liste von Dateipfaden anstelle von Dateinamen zurück, da ich dies als nützlicher empfand. Es gibt einige 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)]
Ich werde ein Beispiel für einen Liner bereitstellen, in dem Quellpfad und Dateityp als Eingabe angegeben werden können. Der Code gibt eine Liste von Dateinamen mit der Erweiterung csv zurück. Verwenden Sie . falls 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.
Wenn Sie verwenden möchten, verwenden Sie globeinfach glob('**/*.csv', recursive=True). Keine Notwendigkeit, dies mit zu kombinieren, um os.walk()zu rekursieren ( recursiveund **werden seit Python 3.5 unterstützt).
Antworten:
os.listdir()
Sie erhalten alles, was sich in einem Verzeichnis befindet - Dateien und Verzeichnisse .Wenn Sie nur Dateien möchten , können Sie diese entweder nach unten filtern
os.path
:oder Sie können verwenden,
os.walk()
was zwei Listen für jedes Verzeichnis ergibt, das es besucht - Aufteilen in Dateien und Verzeichnisse für Sie. Wenn Sie nur das oberste Verzeichnis wollen, können Sie es einfach beim ersten Mal brechenquelle
(_, _, filenames) = walk(mypath).next()
(wenn Sie sicher sind, dass der Spaziergang mindestens einen Wertf.extend(filenames)
ist eigentlich nicht gleichbedeutend mitf = f + filenames
.extend
wirdf
an Ort und Stelle geändert, während durch Hinzufügen eine neue Liste an einem neuen Speicherort erstellt wird. Dies bedeutetextend
im Allgemeinen effizienter als+
, kann jedoch manchmal zu Verwirrung führen, wenn mehrere Objekte Verweise auf die Liste enthalten. Schließlich ist es erwähnenswert, dassf += filenames
dies nicht gleichbedeutendf.extend(filenames)
ist .f = f + filenames
_, _, filenames = next(walk(mypath), (None, None, []))
(_, _, filenames) = next(os.walk(mypath))
Ich bevorzuge die Verwendung des
glob
Moduls, da es Mustervergleich und -erweiterung durchführt.Es wird eine Liste mit den abgefragten Dateien zurückgegeben:
quelle
/home/user/foo/bar/hello.txt
, dann, wenn im Verzeichnis ausgeführt wirdfoo
, dieglob("bar/*.txt")
angezeigt werden kannbar/hello.txt
. Es gibt Fälle, in denen Sie tatsächlich den vollständigen (dh absoluten) Pfad möchten. Für diese Fälle siehe stackoverflow.com/questions/51520/…glob.glob("*")
würde.x=glob.glob("../train/*.png")
werde mir eine Reihe meiner Pfade geben, solange ich den Namen des Ordners kenne. So cool!So erhalten Sie alle Dateien (und Verzeichnisse) im aktuellen Verzeichnis (Python 3)
Im Folgenden finden Sie einfache Methoden zum Abrufen nur von Dateien im aktuellen Verzeichnis mithilfe von
os
und derlistdir()
Funktion in Python 3. Weitere Untersuchungen zeigen, wie Ordner im Verzeichnis zurückgegeben werden. Sie haben die Datei jedoch nicht im Unterverzeichnis kann zu Fuß gehen (später besprochen).Ich fand glob einfacher, die Datei des gleichen Typs oder mit etwas gemeinsamem auszuwählen. Schauen Sie sich das folgende Beispiel an:
Die Funktion gibt eine Liste der angegebenen Erweiterung (.txt, .docx ecc.) Im Argument zurück
Die Funktion gibt jetzt eine Liste der Dateien zurück, die mit der Zeichenfolge übereinstimmen, die Sie als Argument übergeben
Ausgabe
Wie Sie bemerkt haben, haben Sie im obigen Code nicht den vollständigen Pfad der Datei. Wenn Sie den absoluten Pfad benötigen, können Sie eine andere Funktion des
os.path
aufgerufenen Moduls verwenden_getfullpathname
und die Datei, aus der Sie sie erhalten,os.listdir()
als Argument verwenden. Es gibt andere Möglichkeiten, den vollständigen Pfad zu erhalten, wie wir später überprüfen werden (ich habe, wie von mexmex vorgeschlagen, _getfullpathname durch ersetztabspath
).Ich finde das sehr nützlich, um Dinge in vielen Verzeichnissen zu finden, und es hat mir geholfen, eine Datei zu finden, an die ich mich nicht erinnern konnte:
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.
Wenn ich den absoluten Pfad der Dateien benötigen sollte:
Mit
list comprehension
:Alternativ können Sie
pathlib.Path()
anstelle von verwendenpathlib.Path(".")
In diesem Beispiel suchen wir nach der Anzahl der Dateien, die in allen Verzeichnissen und deren Unterverzeichnissen enthalten sind.
Ein Skript, mit dem Sie auf Ihrem Computer alle Dateien eines Typs (Standard: pptx) suchen und in einen neuen Ordner kopieren können.
Falls Sie eine txt-Datei mit allen Dateinamen erstellen möchten:
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.
quelle
gibt eine Liste aller Dateien und Verzeichnisse in "somedirectory" zurück.
quelle
glob.glob
os.listdir()
immer nur Dateinamen zurück (keine relativen Pfade). Wasglob.glob()
zurückkehrt, hängt vom Pfadformat des Eingabemusters ab.Eine einzeilige Lösung, um nur eine Liste von Dateien (keine Unterverzeichnisse) abzurufen:
oder absolute Pfadnamen:
quelle
import os
. Scheint weniger prägnant alsglob()
für mich.glob()
würde es als Datei behandeln. Ihre Methode würde es als Verzeichnis behandeln.Abrufen vollständiger Dateipfade aus einem Verzeichnis und allen seinen Unterverzeichnissen
print full_file_paths
welches 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 beschrieben:
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
quelle
Seit Version 3.4 gibt es dafür eingebaute Iteratoren, die viel effizienter sind als
os.listdir()
:pathlib
: Neu in Version 3.4.Gemäß PEP 428 besteht das Ziel der
pathlib
Bibliothek darin, eine einfache Hierarchie von Klassen bereitzustellen, um Dateisystempfade und die allgemeinen Operationen, die Benutzer über sie ausführen, zu handhaben.os.scandir()
: Neu in Version 3.5.Beachten Sie, dass
os.walk()
verwendetos.scandir()
stattos.listdir()
von 2-20 mal nach erhöht wurde von Version 3.5, und seine Geschwindigkeit 471 PEP .Lassen Sie mich auch empfehlen, den Kommentar von ShadowRanger unten zu lesen.
quelle
list
. Könnte alternativp.name
anstelle der ersten verwendet werden,p
wenn dies bevorzugt wird.pathlib.Path()
Instanzen zu da sie viele nützliche Methoden haben, mit denen ich keinen Abfall verschwenden möchte. Sie könnenstr(p)
sie auch für Pfadnamen aufrufen .os.scandir
Lösung ist effizienter alsos.listdir
bei eineros.path.is_file
Prüfung oder Ähnlichem, selbst wenn Sie eine benötigenlist
(damit Sie nicht von einer verzögerten Iteration profitieren), daos.scandir
vom Betriebssystem bereitgestellte APIs verwendet werden, mit denen Sie dieis_file
Informationen während der Iteration kostenlos erhalten , überhaupt kein Roundtrip pro Datei auf die Festplatte zustat
ihnen (unter WindowsDirEntry
erhalten Siestat
kostenlos vollständige Informationen, auf * NIX-Systemen, diestat
für weitere Informationen erforderlich sindis_file
,is_dir
usw., aberDirEntry
Caches auf den ersten derstat
Einfachheit halber).entry.name
nur den Dateinamen oderentry.path
den vollständigen Pfad abrufen. Nicht mehr überall os.path.join ().Vorbemerkungen
Als die Frage gestellt wurde, stelle ich mir vor, dass Python 2 die LTS- Version war, die Codebeispiele werden jedoch von Python 3 ( .5 ) ausgeführt (ich werde sie so Python 2- konform wie möglich halten; auch jeden dazugehörigen Code Python , das ich veröffentlichen werde, stammt aus Version 3.5.4 (sofern nicht anders angegeben). Dies hat Konsequenzen im Zusammenhang mit einem anderen Schlüsselwort in der Frage: " Fügen Sie sie einer Liste hinzu ":
Die Beispiele basieren auf einem Verzeichnis namens root_dir mit der folgenden Struktur (dieses Beispiel ist für Win , aber ich verwende denselben Baum auch auf Lnx ):
Lösungen
Programmatische Ansätze:
[Python 3]: os. listdir ( path = '.' )
Ein ausführlicheres Beispiel ( code_os_listdir.py ):
Anmerkungen :
Ausgabe :
[Python 3]: os. scandir ( path = '.' ) ( Python 3.5 +, Backport: [PyPI]: scandir )
Anmerkungen :
os.listdir
[Python 3]: os. walk ( top, topdown = True, onerror = None, followlinks = False )
Anmerkungen :
os.scandir
(os.listdir
bei älteren Versionen)[Python 3]: glob. glob ( Pfadname, *, rekursiv = falsch ) ( [Python 3]: glob. iglob ( Pfadname, *, rekursiv = falsch ) )
Anmerkungen :
os.listdir
[Python 3]: Klassenpfad. Pfad ( * Pfadsegmente ) ( Python 3.4 +, Backport: [PyPI]: pathlib2 )
Anmerkungen :
[Python 2]: dircache.listdir (Pfad) (nur Python 2 )
os.listdir
mit Caching[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) über [Python 3]: ctypes - Eine Fremdfunktionsbibliothek für Python ( POSIX- spezifisch)
code_ctypes.py :
Anmerkungen :
os.walk
Format zurück. Ich habe mich nicht darum gekümmert, es rekursiv zu machen, aber ausgehend vom vorhandenen Code wäre das eine ziemlich triviale AufgabeAusgabe :
[ActiveState.Docs]: win32file.FindFilesW ( Win- spezifisch)
Anmerkungen :
win32file.FindFilesW
Teil ist [GitHub]: mhammond / pywin32 - Python für Windows (pywin32) Erweiterungen , die eine ist Python Wrapper über WINAPI sAnmerkungen :
Der Code soll tragbar (mit Ausnahme von Orten, die auf einen bestimmten Bereich abzielen - die markiert sind) oder kreuzweise sein:
In den obigen Varianten wurden mehrere Pfadstile (absolut, Verwandte) verwendet, um die Tatsache zu veranschaulichen, dass die verwendeten "Werkzeuge" in dieser Richtung flexibel sind
os.listdir
undos.scandir
benutze opendir / readdir / closedir ( [MS.Docs]: FindFirstFileW-Funktion / [MS.Docs]: FindNextFileW-Funktion / [MS.Docs]: FindClose-Funktion ) (über [GitHub]: python / cpython - (master) cpython / Module / posixmodule.c )win32file.FindFilesW
verwendet auch diese ( Win- spezifischen) Funktionen (über [GitHub]: mhammond / pywin32 - (master) pywin32 / win32 / src / win32file.i )_get_dir_content (ab Punkt 1 ) kann mit jedem dieser Ansätze implementiert werden (einige erfordern mehr Arbeit und andere weniger).
filter_func=lambda x: True
(dies wird nicht entfernt alles) und in _get_dir_content so etwas wie:if not filter_func(entry_with_path): continue
(Wenn die Funktion für einen Eintrag fehlschlägt, wird sie übersprungen), aber je komplexer der Code wird, desto länger dauert die AusführungNota bene! Da die Rekursion verwendet wird, muss ich erwähnen, dass ich einige Tests auf meinem Laptop ( Win 10 x64 ) durchgeführt habe, die völlig unabhängig von diesem Problem waren, und als die Rekursionsstufe Werte irgendwo im Bereich (990 .. 1000) erreichte ( Rekursionslimit - 1000) (Standard)), ich habe StackOverflow :). Wenn der Verzeichnisbaum diese Grenze überschreitet (ich bin kein FS- Experte, daher weiß ich nicht, ob dies überhaupt möglich ist), könnte dies ein Problem sein.
Ich muss auch erwähnen, dass ich nicht versucht habe, das Rekursionslimit zu erhöhen, da ich keine Erfahrung in diesem Bereich habe (wie viel kann ich erhöhen, bevor ich auch den Stack unter OS erhöhen mussLevel), aber theoretisch besteht immer die Möglichkeit eines Ausfalls, wenn die Dir-Tiefe größer ist als das höchstmögliche Rekursionslimit (auf dieser Maschine).
Die Codebeispiele dienen nur zu Demonstrationszwecken. Das bedeutet, dass ich die Fehlerbehandlung nicht berücksichtigt habe (ich glaube, es gibt keinen Versuch / außer / else / finally- Block), daher ist der Code nicht robust (der Grund ist: ihn so einfach und kurz wie möglich zu halten ). Für die Produktion sollte auch die Fehlerbehandlung hinzugefügt werden
Andere Ansätze:
Verwenden Sie Python nur als Wrapper
Die bekannteste Variante, die ich kenne, ist der sogenannte Systemadministrator- Ansatz:
grep
/findstr
) oder das Formatieren der Ausgabe könnte auf beiden Seiten erfolgen, aber ich werde nicht darauf bestehen. Auch habe ich absichtlichos.system
stattsubprocess.Popen
.Im Allgemeinen ist dieser Ansatz zu vermeiden, da der Parsing-Code ebenfalls angepasst werden sollte , wenn sich das Befehlsausgabeformat zwischen den Betriebssystemversionen / -varianten geringfügig unterscheidet . ganz zu schweigen von den Unterschieden zwischen den Gebietsschemas).
quelle
Ich wirklich mochte adamk Antwort , was darauf hindeutet , dass Sie verwenden
glob()
, aus dem Modul mit dem gleichen Namen. Auf diese Weise können Sie Muster mit*
s abgleichen .Aber wie andere Leute in den Kommentaren
glob()
betonten , kann man über inkonsistente Schrägstriche stolpern. Um dies zu unterstützen, schlage ich vor, dass Sie die Funktionenjoin()
undexpanduser()
imos.path
Modul und möglicherweise auch diegetcwd()
Funktion imos
Modul verwenden.Als Beispiele:
Das Obige ist schrecklich - der Pfad wurde fest codiert und funktioniert unter Windows immer nur zwischen dem Laufwerksnamen und dem
\
s, das im Pfad fest codiert ist.Das Obige funktioniert besser,
Users
hängt jedoch vom Ordnernamen ab, der häufig unter Windows und nicht so häufig unter anderen Betriebssystemen gefunden wird. Es hängt auch davon ab, dass der Benutzer einen bestimmten Namen hatadmin
.Dies funktioniert perfekt auf allen Plattformen.
Ein weiteres großartiges Beispiel, das plattformübergreifend perfekt funktioniert und etwas anderes macht:
Ich hoffe, diese Beispiele helfen Ihnen dabei, die Leistungsfähigkeit einiger Funktionen zu erkennen, die Sie in den Standardmodulen der Python-Bibliothek finden.
quelle
**
funktioniert dies, solange Sie es einstellenrecursive = True
. Siehe die Dokumente hier: docs.python.org/3.5/library/glob.html#glob.globquelle
Wenn Sie nach einer Python-Implementierung von find suchen , ist dies ein Rezept, das ich ziemlich häufig verwende:
Also habe ich ein PyPI- Paket daraus gemacht und es gibt auch ein GitHub-Repository . Ich hoffe, dass jemand es möglicherweise nützlich für diesen Code findet.
quelle
Für bessere Ergebnisse können Sie die
listdir()
Methode desos
Moduls zusammen mit einem Generator verwenden (ein Generator ist ein leistungsstarker Iterator, der seinen Status beibehält, erinnern Sie sich?). Der folgende Code funktioniert mit beiden Versionen einwandfrei: Python 2 und Python 3.Hier ist ein Code:
Die
listdir()
Methode gibt die Liste der Einträge für das angegebene Verzeichnis zurück. Die Methode gibtos.path.isfile()
zurück,True
wenn der angegebene Eintrag eine Datei ist. Deryield
Operator beendet die Funktion, behält jedoch seinen 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.quelle
Das Zurückgeben einer Liste absoluter Dateipfade erfolgt nicht in Unterverzeichnissen
quelle
os.path.abspath(f)
wäre ein etwas billigerer Ersatz füros.path.join(os.getcwd(),f)
.cwd = os.path.abspath('.')
und danncwd
anstelle von'.'
undos.getcwd()
durchgehend verwenden würden, um viele redundante Systemaufrufe zu vermeiden.Hier verwende ich eine rekursive Struktur.
quelle
pathlib
:filter(Path.is_file, Path().rglob('*'))
Ein weiser Lehrer sagte mir einmal:
Ich werde daher eine Lösung für eine Teilmenge des Problems hinzufügen : Oft möchten wir nur prüfen, ob eine Datei mit einer Startzeichenfolge und einer Endzeichenfolge übereinstimmt, ohne in Unterverzeichnisse zu wechseln. Wir möchten daher eine Funktion, die eine Liste von Dateinamen zurückgibt, wie:
Wenn Sie zuerst zwei Funktionen deklarieren möchten, können Sie dies tun:
Diese Lösung kann leicht mit regulären Ausdrücken verallgemeinert werden (und Sie möchten möglicherweise ein
pattern
Argument hinzufügen , wenn Ihre Muster nicht immer am Anfang oder Ende des Dateinamens bleiben sollen).quelle
Generatoren verwenden
quelle
Eine andere gut lesbare Variante für Python 3.4+ ist die Verwendung von pathlib.Path.glob:
Es ist einfach, genauer zu machen, z. B. nur in allen Unterverzeichnissen nach Python-Quelldateien zu suchen, die keine symbolischen Links sind:
quelle
Hier ist meine Allzweckfunktion dafür. Es gibt eine Liste von Dateipfaden anstelle von Dateinamen zurück, da ich dies als nützlicher empfand. Es gibt einige optionale Argumente, die es vielseitig machen. Zum Beispiel benutze ich es oft mit Argumenten wie
pattern='*.txt'
odersubfolders=True
.quelle
Ich werde ein Beispiel für einen Liner bereitstellen, in dem Quellpfad und Dateityp als Eingabe angegeben werden können. Der Code gibt eine Liste von Dateinamen mit der Erweiterung csv zurück. Verwenden Sie . falls 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.
quelle
glob
einfachglob('**/*.csv', recursive=True)
. Keine Notwendigkeit, dies mit zu kombinieren, umos.walk()
zu rekursieren (recursive
und**
werden seit Python 3.5 unterstützt).Für python2: pip installiere rglob
quelle
dircache ist "Veraltet seit Version 2.6: Das dircache-Modul wurde in Python 3.0 entfernt."
quelle