os.listdir()dostaniesz wszystko, co znajduje się w katalogu - pliki i katalogi .
Jeśli chcesz tylko pliki, możesz to przefiltrować, używając os.path:
from os import listdir
from os.path import isfile, join
onlyfiles =[f for f in listdir(mypath)if isfile(join(mypath, f))]
lub można użyć os.walk()która otrzymując dwie listy dla każdego katalogu wizyt it - podział na plikach i katalogów dla ciebie. Jeśli chcesz tylko najwyższy katalog, możesz po prostu złamać go za pierwszym razem
from os import walk
f =[]for(dirpath, dirnames, filenames)in walk(mypath):
f.extend(filenames)break
Nieznaczna modyfikacja do przechowywania pełnych ścieżek: for (ścieżka, nazwy, nazwy plików) w os.walk (mypath): checksum_files.extend (os.path.join (ścieżka / nazwa pliku) dla nazwy pliku w nazwie pliku) przerwa
okigan
150
f.extend(filenames)nie jest tak naprawdę równoważne z f = f + filenames. extendzmodyfikuje fw miejscu, natomiast dodanie tworzy nową listę w nowej lokalizacji pamięci. Oznacza to na extendogół bardziej efektywną niż +, ale czasami może prowadzić do zamieszania, jeśli wiele obiektów zawiera odniesienia do listy. Na koniec warto zauważyć, że f += filenamesjest to równoważne f.extend(filenames), a nief = f + filenames .
Benjamin Hodgson
30
@misterbee, twoje rozwiązanie jest najlepsze, tylko jedna mała poprawka:_, _, filenames = next(walk(mypath), (None, None, []))
bgusach
35
w użyciu w Pythonie 3.x(_, _, filenames) = next(os.walk(mypath))
ET-CS
1677
Wolę używać globmodułu, ponieważ dopasowuje wzorce i rozszerza.
dla wyjaśnienia, nie zwraca to „pełnej ścieżki”; po prostu zwraca ekspansję globu, cokolwiek by to nie było. Na przykład, /home/user/foo/bar/hello.txtjeśli zostanie uruchomiony w katalogu foo, glob("bar/*.txt")zwróci bar/hello.txt. Zdarzają się sytuacje, w których naprawdę potrzebujesz pełnej (tj. Absolutnej) ścieżki; w takich przypadkach zobacz stackoverflow.com/questions/51520/…
piękny!!!! więc .... x=glob.glob("../train/*.png")poda mi tablicę moich ścieżek, o ile znam nazwę folderu. Ale fajnie!
Jennifer Crosby
856
Uzyskaj listę plików w Pythonie 2 i 3
os.listdir()
Jak uzyskać wszystkie pliki (i katalogi) w bieżącym katalogu (Python 3)
Poniżej przedstawiono proste metody pobierania tylko plików z bieżącego katalogu, przy użyciu os i listdir()funkcji w Pythonie 3. Dalsza eksploracja pokaże, jak zwrócić foldery w katalogu, ale nie będziesz mieć pliku w podkatalogu, ponieważ można użyć marszu - omówiono później).
import os
arr = os.listdir()print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
glob
Glob był łatwiejszy do wybrania pliku tego samego typu lub z czymś wspólnym. Spójrz na następujący przykład:
import glob
txtfiles =[]for file in glob.glob("*.txt"):
txtfiles.append(file)
glob ze zrozumieniem listy
import glob
mylist =[f for f in glob.glob("*.txt")]
glob z funkcją
Funkcja zwraca listę danego rozszerzenia (.txt, .docx ecc.) W argumencie
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 rozszerzenie poprzedniego kodu
Funkcja zwraca teraz listę plików pasujących do ciągu przekazywanego jako argument
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)}")
wynik
example found =>[].py found =>['search.py']
Uzyskiwanie pełnej nazwy ścieżki za pomocą os.path.abspath
Jak zauważyłeś, w powyższym kodzie nie masz pełnej ścieżki do pliku. Jeśli potrzebujesz mieć ścieżkę bezwzględną, możesz użyć innej funkcji os.pathmodułu o nazwie _getfullpathname, umieszczając plik, który otrzymujesz os.listdir()jako argument. Istnieją inne sposoby uzyskania pełnej ścieżki, co sprawdzimy później (zastąpiłem, jak sugeruje mexmex, _getfullpathname na 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']
Uzyskaj pełną nazwę ścieżki typu pliku do wszystkich podkatalogów za pomocą walk
Uważam, że jest to bardzo przydatne do znajdowania rzeczy w wielu katalogach i pomogło mi znaleźć plik, o którym nie pamiętałem nazwy:
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(): pobierz pliki w bieżącym katalogu (Python 2)
W Pythonie 2, jeśli chcesz listę plików w bieżącym katalogu, musisz podać argument jako „.” lub os.getcwd () w metodzie os.listdir.
import os
arr = os.listdir('.')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Aby przejść w górę w drzewie katalogów
# Method 1
x = os.listdir('..')# Method 2
x= os.listdir('/')
Pobierz pliki: os.listdir()w określonym katalogu (Python 2 i 3)
import os
arr = os.listdir('F:\\python')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Pobierz pliki z konkretnego podkatalogu za pomocą os.listdir()
import os
x = os.listdir("./content")
os.walk('.') - bieżący katalog
import os
arr = next(os.walk('.'))[2]print(arr)>>>['5bs_Turismo1.pdf','5bs_Turismo1.pptx','esperienza.txt']
next(os.walk('.')) i 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:\\') - uzyskać pełną ścieżkę - zrozumienie listy
[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 - uzyskaj pełną ścieżkę - wszystkie pliki w podkatalogach **
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() - pobierz tylko pliki txt
arr_txt =[x for x in os.listdir()if x.endswith(".txt")]print(arr_txt)>>>['work.txt','3ebooks.txt']
Użycie, globaby uzyskać pełną ścieżkę do plików
Jeśli potrzebuję bezwzględnej ścieżki do plików:
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
Używanie os.path.isfiledo unikania katalogów na liście
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']
Korzystanie pathlibz 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
Z list comprehension:
flist =[p for p in pathlib.Path('.').iterdir()if p.is_file()]
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']
Pobierz tylko pliki z next i przejdź do katalogu
import os
x = next(os.walk('F://python'))[2]print(x)>>>['calculator.bat','calculator.py']
Zdobądź tylko katalogi z next i przejdź do katalogu
import os
next(os.walk('F://python'))[1]# for the current dir use ('.')>>>['python3','others']
Uzyskaj wszystkie nazwy podkatalogów za pomocą 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() z Python 3.5 i nowszych
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
Przykłady:
Dawny. 1: Ile plików jest w podkatalogach?
W tym przykładzie szukamy liczby plików zawartych we wszystkich katalogach i ich podkatalogach.
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'
Przykład 2: Jak skopiować wszystkie pliki z katalogu do innego?
Skrypt służący do porządkowania na komputerze znajdujący wszystkie pliki danego typu (domyślnie: pptx) i kopiujący je w nowym folderze.
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
Dawny. 3: Jak uzyskać wszystkie pliki w pliku txt
Jeśli chcesz utworzyć plik txt ze wszystkimi nazwami plików:
import os
mylist =""with open("filelist.txt","w", encoding="utf-8")as file:for eachfile in os.listdir():
mylist += eachfile +"\n"
file.write(mylist)
Przykład: txt ze wszystkimi plikami na dysku twardym
"""
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")
Cały plik C: \ w jednym pliku tekstowym
To jest krótsza wersja poprzedniego kodu. Zmień folder, w którym chcesz rozpocząć wyszukiwanie plików, jeśli chcesz zacząć od innej pozycji. Ten kod generuje 50 MB pliku tekstowego na moim komputerze z czymś mniejszym niż 500 000 linii z plikami z pełną ścieżką.
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")
Jak napisać plik ze wszystkimi ścieżkami w folderze typu
Za pomocą tej funkcji możesz utworzyć plik txt, który będzie miał nazwę typu pliku, którego szukasz (np. Pngfile.txt) z pełną pełną ścieżką wszystkich plików tego typu. Myślę, że czasem może się przydać.
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
(Nowe) Znajdź wszystkie pliki i otwórz je za pomocą GUI tkinter
Chciałem tylko dodać w tej 2019 roku małą aplikację do wyszukiwania wszystkich plików w katalogu i móc je otworzyć, klikając dwukrotnie nazwę pliku na liście.
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()
To miszmasz zbyt wielu odpowiedzi na pytania, które nie zostały tu zadane. Warto również wyjaśnić, jakie są zastrzeżenia lub zalecane podejścia. Nie ma nic lepszego niż znajomość jednego sposobu w porównaniu do 20 sposobów na zrobienie tego samego, chyba że wiem również, który z nich jest bardziej odpowiedni do użycia.
cs95
OK, JAK NAJSZYBCIEJ Spojrzę na moją odpowiedź i postaram się uczynić ją bardziej czystą i zawierającą bardziej przydatne informacje na temat różnicy między metodami itp.
Giovanni G. PY
Nie powinieneś określać rozszerzenia pliku, sprawdzając, czy nazwa pliku zawiera podciąg. To może powodować wiele problemów. Polecam zawsze sprawdzać, czy nazwa pliku kończy się na określonym podciągu.
ni1ight
Ok, @ n1light Zmieniłem kod ...
Giovanni G. PY
811
import os
os.listdir("somedirectory")
zwróci listę wszystkich plików i katalogów w „somedirectory”.
Tylko jedna linijka, jeśli już ją masz import os. Wydaje się mniej zwięzły niż glob()dla mnie.
ArtOfWarfare
4
problem z glob polega na tym, że folder o nazwie „coś. coś” został zwrócony przez glob („/ home / adam /*.*”)
Remi
6
W OS X jest coś takiego jak pakiet. Jest to katalog, który ogólnie powinien być traktowany jako plik (jak .tar). Czy chcesz, aby traktowano je jako plik lub katalog? Użycie glob()potraktowałoby to jako plik. Twoja metoda potraktowałaby to jak katalog.
ArtOfWarfare
132
Uzyskiwanie pełnych ścieżek plików z katalogu i wszystkich jego podkatalogów
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")
Ścieżka, którą podałem w powyższej funkcji, zawierała 3 pliki - dwa z nich w katalogu głównym, a drugi w podfolderze o nazwie „SUBFOLDER”. Możesz teraz robić takie rzeczy jak:
>>>import pathlib
>>>[p for p in pathlib.Path('.').iterdir()if p.is_file()]
Zgodnie z PEP 428 celem pathlibbiblioteki jest zapewnienie prostej hierarchii klas do obsługi ścieżek systemu plików i wspólnych operacji wykonywanych przez użytkowników.
Dzięki! Myślę, że to jedyne rozwiązanie, które nie zwraca bezpośrednio list. Można użyć p.namezamiast pierwszego palternatywnie, jeśli jest to preferowane.
jeromej
1
Witamy! Wolałbym generować pathlib.Path()instancje, ponieważ mają wiele użytecznych metod, których nie chciałbym marnować. Możesz także do str(p)nich zadzwonić po nazwy ścieżek.
SzieberthAdam
6
Uwaga: os.scandirrozwiązanie będzie bardziej efektywne niż os.listdirz os.path.is_fileczekiem lub podobne, nawet jeśli potrzebujesz list(więc nie korzystają z leniwej iteracji), ponieważ os.scandirużywa API OS pod warunkiem że daje is_fileinformacje za darmo, jak to iteracje , obie strony nie per-pliku na dysku do statnich w ogóle (na Windows, DirEntrya Ci kompletne statinformacje za darmo, na systemach * NIX musi statInformacje o zaświatach is_file, is_diritp, ale DirEntrybuforuje na pierwszy statdla wygody).
ShadowRanger
1
Możesz także użyć, entry.nameaby uzyskać tylko nazwę pliku lub entry.pathuzyskać pełną ścieżkę. Nigdy więcej os.path.join () w całym miejscu.
user136036
56
Uwagi wstępne
Chociaż w tekście pytania istnieje wyraźne rozróżnienie między terminami plików i katalogów , niektórzy mogą argumentować, że katalogi są w rzeczywistości plikami specjalnymi
Stwierdzenie: „ wszystkie pliki katalogu ” można interpretować na dwa sposoby:
Wszystkie bezpośrednie (poziom 1) lub potomkowie tylko
Wszyscy potomkowie w całym drzewie katalogów (łącznie z tymi w podkatalogach)
Kiedy pytanie zostało zadane, wyobrażam sobie, że Python 2 był wersją LTS , jednak próbki kodu będą uruchamiane przez Python 3 ( .5 ) (Będę utrzymywał ich zgodność z Pythonem 2, jak to możliwe; również każdy kod należący do Python, który zamierzam opublikować, pochodzi z wersji 3.5.4 - chyba że podano inaczej). Ma to konsekwencje związane z innym słowem kluczowym w pytaniu: „ dodaj je do listy ”:
W wersjach wcześniejszych niż Python 2.2 sekwencje (iterowalne) były w większości reprezentowane przez listy (krotki, zbiory, ...)
W Pythonie 2.2 koncepcja generatora ( [Python.Wiki]: Generatory ) - dzięki uprzejmości [Python 3]: instrukcja fed ). Z biegiem czasu zaczęły pojawiać się odpowiedniki generatorów dla funkcji, które zwróciły / działały z listami
W Python 3 generator jest zachowaniem domyślnym
Nie jestem pewien, czy zwrócenie listy jest nadal obowiązkowe (lub generator też by to zrobił), ale przekazanie generatora do konstruktora listy utworzy z niego listę (a także ją wykorzysta). Poniższy przykład ilustruje różnice w [Python 3]: map ( function, iterable, ... )
>>>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'>)
Przykłady będą oparte na katalogu o nazwie katalog_główny o następującej strukturze (ten przykład dotyczy Win , ale używam tego samego drzewa na Lnx ):
Zwraca listę zawierającą nazwy pozycji w katalogu podaną przez ścieżkę. Lista jest w dowolnej kolejności i nie zawiera wpisów specjalnych '.'oraz '..'...
>>>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']
Bardziej szczegółowy przykład ( 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()
Uwagi :
Istnieją dwie implementacje:
Ten, który korzysta z generatorów (oczywiście tutaj wydaje się bezużyteczny, ponieważ natychmiast przekonwertowałem wynik na listę)
Klasyczny (nazwy funkcji kończące się na _old )
Wykorzystywana jest rekurencja (aby dostać się do podkatalogów)
Dla każdej implementacji istnieją dwie funkcje:
Ten, który zaczyna się od znaku podkreślenia ( _ ): „prywatny” (nie powinien być wywoływany bezpośrednio) - to robi całą pracę
Publiczny (opakowanie powyżej): po prostu usuwa początkową ścieżkę (jeśli jest wymagana) ze zwróconych wpisów. To brzydka implementacja, ale to jedyny pomysł, który mógłbym w tym momencie wymyślić
Pod względem wydajności generatory są zazwyczaj nieco szybsze (biorąc pod uwagę zarówno tworzenie, jak i iterację) ), ale nie testowałem ich w funkcjach rekurencyjnych, a także iteruję wewnątrz funkcji nad wewnętrznymi generatorami - nie wiem, jak wydajność przyjazne jest to
Graj z argumentami, aby uzyskać różne wyniki
Wyjście :
(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']
Zwraca iterator obiektów os.DirEntry odpowiadających pozycjom w katalogu podanym przez path . Wpisy są przedstawiane w dowolnej kolejności, a wpisy specjalne '.'i '..'nie są uwzględniane.
Użycie scandir () zamiast listdir () może znacznie zwiększyć wydajność kodu, który również potrzebuje informacji o typie pliku lub atrybucie pliku, ponieważ obiekty os.DirEntry ujawniają te informacje, jeśli system operacyjny udostępnia je podczas skanowania katalogu. Wszystkie metody os.DirEntry mogą wykonywać wywołanie systemowe, ale is_dir () i is_file () zwykle wymagają tylko wywołania systemowego dla dowiązań symbolicznych; os.DirEntry.stat () zawsze wymaga wywołania systemowego w systemie Unix, ale wymaga tylko jednego dla dowiązań symbolicznych w systemie Windows.
>>>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
Uwagi :
Jest podobny do os.listdir
Ale jest również bardziej elastyczny (i oferuje więcej funkcji), więcej Python ic (aw niektórych przypadkach szybszy)
Wygeneruj nazwy plików w drzewie katalogów, chodząc po drzewie od góry do dołu lub od dołu do góry. Dla każdego katalogu w drzewie katalogów zakorzenionej w górę (w tym szczyt sam), to daje 3-krotki ( 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',[],[])
Uwagi :
W scenach używa os.scandir( os.listdirw starszych wersjach)
Wykonuje ciężkie podnoszenie, powtarzając się w podfolderach
Zwraca możliwie pustą listę nazw ścieżek , które pasują do nazwy ścieżki , która musi być łańcuchem zawierającym specyfikację ścieżki. ścieżka może być bezwzględna (podobna /usr/src/Python-1.5/Makefile) lub względna (podobna ../../Tools/*/*.gif) i może zawierać symbole wieloznaczne w stylu powłoki. Zepsute dowiązania symboliczne są uwzględniane w wynikach (jak w powłoce). ... Zmieniono w wersji 3.5 : Obsługa globów rekurencyjnych za pomocą „ **”.
>>>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
Uwagi :
Używa os.listdir
W przypadku dużych drzew (szczególnie jeśli włączona jest funkcja rekurencyjna ) preferowany jest program iglob
Umożliwia zaawansowane filtrowanie na podstawie nazwy (ze względu na symbol wieloznaczny)
>>>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']
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 to obca biblioteka funkcji dla Pythona. Zapewnia typy danych kompatybilne z C i umożliwia wywoływanie funkcji w bibliotekach DLL lub bibliotekach udostępnionych. Można go użyć do zawinięcia tych bibliotek w czysty Python.
LinuxDirent64 jest ctypes reprezentacja struct dirent64 z [Man7]: dirent.h (0P) (jak to DT_ stałymi) z moim maszyny: Ubtu 16 64 ( 4.10.0-40-rodzajowe i libc6-dev: amd64 ). W innych smakach / wersjach definicja struktury może się różnić, a jeśli tak, należy zaktualizować alias ctypes , w przeciwnym razie spowoduje to niezdefiniowane zachowanie
Zwraca dane w os.walkformacie. Nie zadałem sobie trudu, aby uczynić go rekurencyjnym, ale zaczynając od istniejącego kodu, byłoby to dość trywialne zadanie
Wszystko jest wykonalne również w Win , dane (biblioteki, funkcje, struktury, stałe, ...) różnią się
Wyjście :
[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']]
Pobiera listę pasujących nazw plików przy użyciu interfejsu Windows Unicode API. Interfejs funkcji API FindFirstFileW / FindNextFileW / Find close.
>>>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']
Link do dokumentacji pochodzi z ActiveState , ponieważ nie znalazłem żadnej oficjalnej dokumentacji PyWin32
Zainstaluj jakiś pakiet innej firmy, który załatwi sprawę
Najprawdopodobniej będzie polegać na jednym (lub więcej) z powyższych (może z niewielkimi dostosowaniami)
Uwagi :
Kod ma być przenośny (z wyjątkiem miejsc kierowanych na określony obszar - które są oznaczone) lub krzyżować:
platforma ( Nix , Win ,)
Wersja Python (2, 3,)
W powyższych wariantach zastosowano wiele stylów ścieżek (bezwzględne, względne), aby zilustrować fakt, że stosowane „narzędzia” są elastyczne w tym kierunku
_get_dir_content (od punktu 1. ) może być zaimplementowany przy użyciu dowolnego z tych podejść (niektóre będą wymagały więcej pracy, a inne mniej)
Można wykonać zaawansowane filtrowanie (zamiast tylko pliku vs. katalog ): np. Argument include_folders można zastąpić innym (np. Filter_func ), który byłby funkcją, która przyjmuje ścieżkę jako argument: filter_func=lambda x: True(nie usuwa się cokolwiek) i wewnątrz _get_dir_content coś takiego: if not filter_func(entry_with_path): continue(jeśli funkcja nie powiedzie się dla jednego wpisu, zostanie pominięta), ale im bardziej skomplikowany staje się kod, tym dłużej trwa wykonanie
Nota bene! Ponieważ używana jest rekurencja, muszę wspomnieć, że wykonałem kilka testów na moim laptopie ( Win 10 x64 ), całkowicie niezwiązanych z tym problemem, a kiedy poziom rekurencji osiągał wartości gdzieś w zakresie (990 .. 1000) ( recursionlimit - 1000 (domyślnie)), mam StackOverflow :). Jeśli drzewo katalogów przekroczy ten limit (nie jestem ekspertem FS , więc nie wiem, czy to w ogóle możliwe), może to stanowić problem.
Muszę również wspomnieć, że nie próbowałem zwiększać ograniczenia rekursji, ponieważ nie mam doświadczenia w tej dziedzinie (o ile mogę go zwiększyć, zanim będę musiał zwiększyć stos w OS) poziomu ograniczenia ), ale teoretycznie zawsze będzie możliwość niepowodzenia, jeśli głębokość katalogu jest większa niż najwyższa możliwa rekursja ograniczenia (na tej maszynie)
Próbki kodu służą wyłącznie do celów demonstracyjnych. Oznacza to, że nie wziąłem pod uwagę obsługi błędów (nie sądzę, aby istniała jakakolwiek próba / oprócz / else / wreszcie blok), więc kod nie jest niezawodny (powodem jest to, aby był tak prosty i krótki, jak to możliwe) ). W przypadku produkcji należy również dodać obsługę błędów
Inne podejścia:
Używaj Pythona tylko jako opakowania
Wszystko odbywa się przy użyciu innej technologii
Ta technologia jest wywoływana z Pythona
Najsłynniejszym znanym mi smakiem jest to, co nazywam podejściem administratora systemu :
Użyj Pythona (lub dowolnego innego języka programowania w tym zakresie), aby wykonywać polecenia powłoki (i analizować ich wyniki)
Niektórzy uważają to za porządny hack
Uważam to bardziej za kiepskie obejście ( gainarie ), ponieważ akcja per se jest wykonywana z powłoki ( w tym przypadku cmd ), a zatem nie ma nic wspólnego z Pythonem .
Filtrowanie ( grep/ findstr) lub formatowanie wyjściowe można wykonać po obu stronach, ale nie zamierzam tego nalegać. Również celowo użyłem os.systemzamiast subprocess.Popen.
Zasadniczo należy unikać tego podejścia, ponieważ jeśli niektóre formaty wyjściowe poleceń nieco różnią się między wersjami / smakami systemu operacyjnego , należy również dostosować kod analizujący; nie wspominając o różnicach między lokalizacjami).
Naprawdę podobała mi się odpowiedź Adama , sugerująca użycie glob(), z modułu o tej samej nazwie. Pozwala to na dopasowanie wzorca do *s.
Ale jak zauważyli inni w komentarzach, glob()mogą się potknąć niespójnymi kierunkami cięcia. Aby temu zaradzić, sugeruję użycie funkcji join()i expanduser()w os.pathmodule, a być może także getcwd()funkcji w osmodule.
Jako przykłady:
from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')
Powyższe jest okropne - ścieżka została zakodowana na stałe i zawsze będzie działała w systemie Windows między nazwą dysku a \literą „s” zakodowaną na ścieżce.
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'))
Powyższe działa lepiej, ale opiera się na nazwie folderu, Usersktóra często znajduje się w systemie Windows, a nie tak często w innych systemach operacyjnych. Powołuje się on także na użytkownika posiadającego specyficzną nazwę, 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'))
Działa to doskonale na wszystkich platformach.
Kolejny świetny przykład, który działa idealnie na różnych platformach i robi coś nieco innego:
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'))
Mam nadzieję, że te przykłady pomogą ci zobaczyć moc kilku funkcji, które można znaleźć w standardowych modułach bibliotecznych Python.
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
Aby uzyskać lepsze wyniki, możesz użyć listdir()metody osmodułu razem z generatorem (generator to potężny iterator, który utrzymuje swój stan, pamiętasz?). Poniższy kod działa poprawnie w obu wersjach: Python 2 i Python 3.
Oto kod:
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)
listdir()Metoda zwraca listę wpisów dla danego katalogu. Metoda os.path.isfile()zwraca, Truejeśli podany wpis jest plikiem. A yieldoperator rezygnuje FUNC ale zachowuje swój aktualny stan, i zwraca tylko nazwę wejściu wykryte jako plik. Wszystkie powyższe pozwalają nam zapętlić funkcję generatora.
Uwaga: os.path.abspath(f)byłby nieco tańszym zamiennikiem os.path.join(os.getcwd(),f).
ShadowRanger
Byłbym bardziej wydajny, gdybyś zaczął cwd = os.path.abspath('.'), a następnie używał cwdzamiast '.'i os.getcwd()przez cały czas, aby uniknąć mnóstwa zbędnych wywołań systemowych.
To samo można osiągnąć tylko w jednej linii z pathlib:filter(Path.is_file, Path().rglob('*'))
Georgy
9
Mądry nauczyciel powiedział mi kiedyś, że:
Gdy istnieje kilka ustalonych sposobów na zrobienie czegoś, żaden z nich nie jest dobry dla wszystkich przypadków.
W ten sposób dodam rozwiązanie dla podzbioru problemu: dość często chcemy tylko sprawdzić, czy plik pasuje do łańcucha początkowego i łańcucha końcowego, bez wchodzenia do podkatalogów. Dlatego chcielibyśmy funkcji, która zwraca listę nazw plików, na przykład:
Jeśli chcesz najpierw zadeklarować dwie funkcje, możesz to zrobić:
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)]
To rozwiązanie można łatwo uogólnić za pomocą wyrażeń regularnych (i możesz chcieć dodać patternargument, jeśli nie chcesz, aby twoje wzorce zawsze trzymały się początku lub końca nazwy pliku).
Oto moja funkcja ogólnego przeznaczenia do tego. Zwraca listę ścieżek do plików zamiast nazw plików, ponieważ uważam, że jest to bardziej przydatne. Ma kilka opcjonalnych argumentów, dzięki którym jest wszechstronny. Na przykład często używam go z argumentami takimi jak pattern='*.txt'lub 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)]
Podam przykładową linijkę, w której jako źródło można podać sourcepath i typ pliku. Kod zwraca listę nazw plików z rozszerzeniem csv. Zastosowanie . na wypadek, gdyby wszystkie pliki musiały zostać zwrócone. Spowoduje to również rekurencyjne skanowanie podkatalogów.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
W razie potrzeby zmodyfikuj rozszerzenia plików i ścieżkę źródłową.
Jeśli zamierzasz użyć glob, po prostu użyj glob('**/*.csv', recursive=True). Nie ma potrzeby łączenia tego z os.walk()rekurencją ( recursivei **są obsługiwane od wersji Python 3.5).
Odpowiedzi:
os.listdir()
dostaniesz wszystko, co znajduje się w katalogu - pliki i katalogi .Jeśli chcesz tylko pliki, możesz to przefiltrować, używając
os.path
:lub można użyć
os.walk()
która otrzymując dwie listy dla każdego katalogu wizyt it - podział na plikach i katalogów dla ciebie. Jeśli chcesz tylko najwyższy katalog, możesz po prostu złamać go za pierwszym razemźródło
(_, _, filenames) = walk(mypath).next()
f.extend(filenames)
nie jest tak naprawdę równoważne zf = f + filenames
.extend
zmodyfikujef
w miejscu, natomiast dodanie tworzy nową listę w nowej lokalizacji pamięci. Oznacza to naextend
ogół bardziej efektywną niż+
, ale czasami może prowadzić do zamieszania, jeśli wiele obiektów zawiera odniesienia do listy. Na koniec warto zauważyć, żef += filenames
jest to równoważnef.extend(filenames)
, a nief = f + filenames
._, _, filenames = next(walk(mypath), (None, None, []))
(_, _, filenames) = next(os.walk(mypath))
Wolę używać
glob
modułu, ponieważ dopasowuje wzorce i rozszerza.Zwróci listę z zapytanymi plikami:
źródło
/home/user/foo/bar/hello.txt
jeśli zostanie uruchomiony w katalogufoo
,glob("bar/*.txt")
zwrócibar/hello.txt
. Zdarzają się sytuacje, w których naprawdę potrzebujesz pełnej (tj. Absolutnej) ścieżki; w takich przypadkach zobacz stackoverflow.com/questions/51520/…glob.glob("*")
by.x=glob.glob("../train/*.png")
poda mi tablicę moich ścieżek, o ile znam nazwę folderu. Ale fajnie!Jak uzyskać wszystkie pliki (i katalogi) w bieżącym katalogu (Python 3)
Poniżej przedstawiono proste metody pobierania tylko plików z bieżącego katalogu, przy użyciu
os
ilistdir()
funkcji w Pythonie 3. Dalsza eksploracja pokaże, jak zwrócić foldery w katalogu, ale nie będziesz mieć pliku w podkatalogu, ponieważ można użyć marszu - omówiono później).Glob był łatwiejszy do wybrania pliku tego samego typu lub z czymś wspólnym. Spójrz na następujący przykład:
Funkcja zwraca listę danego rozszerzenia (.txt, .docx ecc.) W argumencie
Funkcja zwraca teraz listę plików pasujących do ciągu przekazywanego jako argument
wynik
Jak zauważyłeś, w powyższym kodzie nie masz pełnej ścieżki do pliku. Jeśli potrzebujesz mieć ścieżkę bezwzględną, możesz użyć innej funkcji
os.path
modułu o nazwie_getfullpathname
, umieszczając plik, który otrzymujeszos.listdir()
jako argument. Istnieją inne sposoby uzyskania pełnej ścieżki, co sprawdzimy później (zastąpiłem, jak sugeruje mexmex, _getfullpathname naabspath
).Uważam, że jest to bardzo przydatne do znajdowania rzeczy w wielu katalogach i pomogło mi znaleźć plik, o którym nie pamiętałem nazwy:
W Pythonie 2, jeśli chcesz listę plików w bieżącym katalogu, musisz podać argument jako „.” lub os.getcwd () w metodzie os.listdir.
Jeśli potrzebuję bezwzględnej ścieżki do plików:
Z
list comprehension
:Alternatywnie użyj
pathlib.Path()
zamiastpathlib.Path(".")
W tym przykładzie szukamy liczby plików zawartych we wszystkich katalogach i ich podkatalogach.
Skrypt służący do porządkowania na komputerze znajdujący wszystkie pliki danego typu (domyślnie: pptx) i kopiujący je w nowym folderze.
Jeśli chcesz utworzyć plik txt ze wszystkimi nazwami plików:
Za pomocą tej funkcji możesz utworzyć plik txt, który będzie miał nazwę typu pliku, którego szukasz (np. Pngfile.txt) z pełną pełną ścieżką wszystkich plików tego typu. Myślę, że czasem może się przydać.
źródło
zwróci listę wszystkich plików i katalogów w „somedirectory”.
źródło
glob.glob
os.listdir()
zawsze zwraca same nazwy plików (nie ścieżki względne). To, coglob.glob()
zwraca, zależy od formatu ścieżki wzorca wejściowego.Jedno-liniowe rozwiązanie do zdobycia tylko listę plików (bez podkatalogów):
lub bezwzględne nazwy ścieżek:
źródło
import os
. Wydaje się mniej zwięzły niżglob()
dla mnie.glob()
potraktowałoby to jako plik. Twoja metoda potraktowałaby to jak katalog.Uzyskiwanie pełnych ścieżek plików z katalogu i wszystkich jego podkatalogów
print full_file_paths
który wydrukuje listę:['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
Jeśli chcesz, możesz otworzyć i odczytać zawartość lub skoncentrować się tylko na plikach z rozszerzeniem „.dat”, jak w poniższym kodzie:
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
źródło
Od wersji 3.4 są do tego wbudowane iteratory, które są znacznie wydajniejsze niż
os.listdir()
:pathlib
: Nowość w wersji 3.4.Zgodnie z PEP 428 celem
pathlib
biblioteki jest zapewnienie prostej hierarchii klas do obsługi ścieżek systemu plików i wspólnych operacji wykonywanych przez użytkowników.os.scandir()
: Nowość w wersji 3.5.Zauważ, że
os.walk()
używaos.scandir()
zamiastos.listdir()
z wersji 3.5, a jego prędkość wzrosła o 2-20 razy zgodnie z PEP 471 .Pozwól mi również polecić przeczytanie komentarza ShadowRanger poniżej.
źródło
list
. Można użyćp.name
zamiast pierwszegop
alternatywnie, jeśli jest to preferowane.pathlib.Path()
instancje, ponieważ mają wiele użytecznych metod, których nie chciałbym marnować. Możesz także dostr(p)
nich zadzwonić po nazwy ścieżek.os.scandir
rozwiązanie będzie bardziej efektywne niżos.listdir
zos.path.is_file
czekiem lub podobne, nawet jeśli potrzebujeszlist
(więc nie korzystają z leniwej iteracji), ponieważos.scandir
używa API OS pod warunkiem że dajeis_file
informacje za darmo, jak to iteracje , obie strony nie per-pliku na dysku dostat
nich w ogóle (na Windows,DirEntry
a Ci kompletnestat
informacje za darmo, na systemach * NIX musistat
Informacje o zaświatachis_file
,is_dir
itp, aleDirEntry
buforuje na pierwszystat
dla wygody).entry.name
aby uzyskać tylko nazwę pliku lubentry.path
uzyskać pełną ścieżkę. Nigdy więcej os.path.join () w całym miejscu.Uwagi wstępne
Kiedy pytanie zostało zadane, wyobrażam sobie, że Python 2 był wersją LTS , jednak próbki kodu będą uruchamiane przez Python 3 ( .5 ) (Będę utrzymywał ich zgodność z Pythonem 2, jak to możliwe; również każdy kod należący do Python, który zamierzam opublikować, pochodzi z wersji 3.5.4 - chyba że podano inaczej). Ma to konsekwencje związane z innym słowem kluczowym w pytaniu: „ dodaj je do listy ”:
Przykłady będą oparte na katalogu o nazwie katalog_główny o następującej strukturze (ten przykład dotyczy Win , ale używam tego samego drzewa na Lnx ):
Rozwiązania
Podejścia programowe:
[Python 3]: os. listdir ( ścieżka = '.' )
Bardziej szczegółowy przykład ( code_os_listdir.py ):
Uwagi :
Wyjście :
[Python 3]: os. scandir ( ścieżka = '.' ) ( Python 3.5 +, backport: [PyPI]: scandir )
Uwagi :
os.listdir
[Python 3]: os. spacer ( top, topdown = True, onerror = None, followlinks = False )
Uwagi :
os.scandir
(os.listdir
w starszych wersjach)[Python 3]: glob. glob ( ścieżka, *, recursive = False ) ( [Python 3]: glob. iglob ( ścieżka, *, recursive = False ) )
Uwagi :
os.listdir
[Python 3]: ścieżka klasy. Ścieżka ( * pathsegments ) ( Python 3.4 +, backport: [PyPI]: pathlib2 )
Uwagi :
[Python 2]: dircache.listdir (ścieżka) ( tylko Python 2 )
os.listdir
z buforowaniem[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) przez [Python 3]: ctypes - Biblioteka funkcji obcych dla Pythona ( specyficzna dla POSIX )
code_ctypes.py :
Uwagi :
os.walk
formacie. Nie zadałem sobie trudu, aby uczynić go rekurencyjnym, ale zaczynając od istniejącego kodu, byłoby to dość trywialne zadanieWyjście :
[ActiveState.Docs]: win32file.FindFilesW ( specyficzne dla systemu Win )
Notatki :
win32file.FindFilesW
jest częścią [GitHub]: mhammond / pywin32 - Rozszerzenia Python dla Windows (pywin32) , które są Pythonem owijka WINAPI sUwagi :
Kod ma być przenośny (z wyjątkiem miejsc kierowanych na określony obszar - które są oznaczone) lub krzyżować:
W powyższych wariantach zastosowano wiele stylów ścieżek (bezwzględne, względne), aby zilustrować fakt, że stosowane „narzędzia” są elastyczne w tym kierunku
os.listdir
ios.scandir
użyj opendir / readdir / closedir ( [MS.Docs]: FindFirstFileW function / [MS.Docs]: FindNextFileW function / [MS.Docs]: FindClose function ) (przez [GitHub]: python / cpython - (master) cpython / Modules / posixmodule.c )win32file.FindFilesW
używa również tych funkcji ( specyficznych dla Win ) (przez [GitHub]: mhammond / pywin32 - (master) pywin32 / win32 / src / win32file.i )_get_dir_content (od punktu 1. ) może być zaimplementowany przy użyciu dowolnego z tych podejść (niektóre będą wymagały więcej pracy, a inne mniej)
filter_func=lambda x: True
(nie usuwa się cokolwiek) i wewnątrz _get_dir_content coś takiego:if not filter_func(entry_with_path): continue
(jeśli funkcja nie powiedzie się dla jednego wpisu, zostanie pominięta), ale im bardziej skomplikowany staje się kod, tym dłużej trwa wykonanieNota bene! Ponieważ używana jest rekurencja, muszę wspomnieć, że wykonałem kilka testów na moim laptopie ( Win 10 x64 ), całkowicie niezwiązanych z tym problemem, a kiedy poziom rekurencji osiągał wartości gdzieś w zakresie (990 .. 1000) ( recursionlimit - 1000 (domyślnie)), mam StackOverflow :). Jeśli drzewo katalogów przekroczy ten limit (nie jestem ekspertem FS , więc nie wiem, czy to w ogóle możliwe), może to stanowić problem.
Muszę również wspomnieć, że nie próbowałem zwiększać ograniczenia rekursji, ponieważ nie mam doświadczenia w tej dziedzinie (o ile mogę go zwiększyć, zanim będę musiał zwiększyć stos w OS) poziomu ograniczenia ), ale teoretycznie zawsze będzie możliwość niepowodzenia, jeśli głębokość katalogu jest większa niż najwyższa możliwa rekursja ograniczenia (na tej maszynie)
Próbki kodu służą wyłącznie do celów demonstracyjnych. Oznacza to, że nie wziąłem pod uwagę obsługi błędów (nie sądzę, aby istniała jakakolwiek próba / oprócz / else / wreszcie blok), więc kod nie jest niezawodny (powodem jest to, aby był tak prosty i krótki, jak to możliwe) ). W przypadku produkcji należy również dodać obsługę błędów
Inne podejścia:
Używaj Pythona tylko jako opakowania
Najsłynniejszym znanym mi smakiem jest to, co nazywam podejściem administratora systemu :
grep
/findstr
) lub formatowanie wyjściowe można wykonać po obu stronach, ale nie zamierzam tego nalegać. Również celowo użyłemos.system
zamiastsubprocess.Popen
.Zasadniczo należy unikać tego podejścia, ponieważ jeśli niektóre formaty wyjściowe poleceń nieco różnią się między wersjami / smakami systemu operacyjnego , należy również dostosować kod analizujący; nie wspominając o różnicach między lokalizacjami).
źródło
Naprawdę podobała mi się odpowiedź Adama , sugerująca użycie
glob()
, z modułu o tej samej nazwie. Pozwala to na dopasowanie wzorca do*
s.Ale jak zauważyli inni w komentarzach,
glob()
mogą się potknąć niespójnymi kierunkami cięcia. Aby temu zaradzić, sugeruję użycie funkcjijoin()
iexpanduser()
wos.path
module, a być może takżegetcwd()
funkcji wos
module.Jako przykłady:
Powyższe jest okropne - ścieżka została zakodowana na stałe i zawsze będzie działała w systemie Windows między nazwą dysku a
\
literą „s” zakodowaną na ścieżce.Powyższe działa lepiej, ale opiera się na nazwie folderu,
Users
która często znajduje się w systemie Windows, a nie tak często w innych systemach operacyjnych. Powołuje się on także na użytkownika posiadającego specyficzną nazwę,admin
.Działa to doskonale na wszystkich platformach.
Kolejny świetny przykład, który działa idealnie na różnych platformach i robi coś nieco innego:
Mam nadzieję, że te przykłady pomogą ci zobaczyć moc kilku funkcji, które można znaleźć w standardowych modułach bibliotecznych Python.
źródło
**
działa tak długo, jak ustawiszrecursive = True
. Zobacz dokumenty tutaj: docs.python.org/3.5/library/glob.html#glob.globźródło
Jeśli szukasz implementacji find w Pythonie , jest to przepis, którego używam dość często:
Zrobiłem z niego pakiet PyPI i istnieje również repozytorium GitHub . Mam nadzieję, że ktoś uzna to za potencjalnie przydatne dla tego kodu.
źródło
Aby uzyskać lepsze wyniki, możesz użyć
listdir()
metodyos
modułu razem z generatorem (generator to potężny iterator, który utrzymuje swój stan, pamiętasz?). Poniższy kod działa poprawnie w obu wersjach: Python 2 i Python 3.Oto kod:
listdir()
Metoda zwraca listę wpisów dla danego katalogu. Metodaos.path.isfile()
zwraca,True
jeśli podany wpis jest plikiem. Ayield
operator rezygnuje FUNC ale zachowuje swój aktualny stan, i zwraca tylko nazwę wejściu wykryte jako plik. Wszystkie powyższe pozwalają nam zapętlić funkcję generatora.źródło
Zwracanie listy bezwzględnych ścieżek plików, nie powraca do podkatalogów
źródło
os.path.abspath(f)
byłby nieco tańszym zamiennikiemos.path.join(os.getcwd(),f)
.cwd = os.path.abspath('.')
, a następnie używałcwd
zamiast'.'
ios.getcwd()
przez cały czas, aby uniknąć mnóstwa zbędnych wywołań systemowych.Tutaj używam struktury rekurencyjnej.
źródło
pathlib
:filter(Path.is_file, Path().rglob('*'))
Mądry nauczyciel powiedział mi kiedyś, że:
W ten sposób dodam rozwiązanie dla podzbioru problemu: dość często chcemy tylko sprawdzić, czy plik pasuje do łańcucha początkowego i łańcucha końcowego, bez wchodzenia do podkatalogów. Dlatego chcielibyśmy funkcji, która zwraca listę nazw plików, na przykład:
Jeśli chcesz najpierw zadeklarować dwie funkcje, możesz to zrobić:
To rozwiązanie można łatwo uogólnić za pomocą wyrażeń regularnych (i możesz chcieć dodać
pattern
argument, jeśli nie chcesz, aby twoje wzorce zawsze trzymały się początku lub końca nazwy pliku).źródło
Korzystanie z generatorów
źródło
Innym bardzo czytelnym wariantem dla Python 3.4+ jest pathlib.Path.glob:
Łatwiej jest sprecyzować, np. Szukać tylko plików źródłowych Pythona, które nie są dowiązaniami symbolicznymi, również we wszystkich podkatalogach:
źródło
Oto moja funkcja ogólnego przeznaczenia do tego. Zwraca listę ścieżek do plików zamiast nazw plików, ponieważ uważam, że jest to bardziej przydatne. Ma kilka opcjonalnych argumentów, dzięki którym jest wszechstronny. Na przykład często używam go z argumentami takimi jak
pattern='*.txt'
lubsubfolders=True
.źródło
Podam przykładową linijkę, w której jako źródło można podać sourcepath i typ pliku. Kod zwraca listę nazw plików z rozszerzeniem csv. Zastosowanie . na wypadek, gdyby wszystkie pliki musiały zostać zwrócone. Spowoduje to również rekurencyjne skanowanie podkatalogów.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
W razie potrzeby zmodyfikuj rozszerzenia plików i ścieżkę źródłową.
źródło
glob
, po prostu użyjglob('**/*.csv', recursive=True)
. Nie ma potrzeby łączenia tego zos.walk()
rekurencją (recursive
i**
są obsługiwane od wersji Python 3.5).Dla python2: pip zainstaluj rglob
źródło
dircache jest „Przestarzałe od wersji 2.6: Moduł dircache został usunięty w Pythonie 3.0”.
źródło