Muszę iterować po podkatalogach danego katalogu i szukać plików. Jeśli otrzymam plik, muszę go otworzyć, zmienić zawartość i zastąpić go własnymi wierszami.
Próbowałem tego:
import os
rootdir ='C:/Users/sid/Desktop/test'
for subdir, dirs, files in os.walk(rootdir):
for file in files:
f=open(file,'r')
lines=f.readlines()
f.close()
f=open(file,'w')
for line in lines:
newline = "No you are not"
f.write(newline)
f.close()
ale pojawia się błąd. Co ja robię źle?
Odpowiedzi:
Rzeczywisty spacer po katalogach działa tak, jak został zakodowany. Jeśli zastąpisz zawartość wewnętrznej pętli prostą
print
instrukcją, zobaczysz, że każdy plik został znaleziony:Jeśli nadal pojawiają się błędy podczas wykonywania powyższych czynności, podaj komunikat o błędzie.
Zaktualizowano dla Python3
źródło
Innym sposobem powrocie wszystkie pliki w podkatalogach jest skorzystanie z
pathlib
modułu , wprowadzony w Pythonie 3.4, który zapewnia zorientowanego podejścia obiektowego do obsługi ścieżek systemu plików (Pathlib jest również dostępny na Pythona 2.7 za pośrednictwem modułu pathlib2 na PyPI ):Od Pythona 3.5,
glob
moduł obsługuje również rekurencyjne wyszukiwanie plików:Z
file_list
jednego z powyższych podejść można iterować bez potrzeby zagnieżdżonej pętli:źródło
pathlib
siebie, głównie dlatego, że lubię składnię metod obiektowych. Istnieją inne różnice, na przykład biblioteka ścieżek zwraca określone klasy ścieżek zamiast ciągów znaków, a dostępne funkcje różnią się między bibliotekami (np.os.path.expanduser('~')
VsPath.home()
). Przejrzyj dokumentację i zobacz, które podejście preferujesz.**
wzorzec glob, możesz użyćrglob
.Od 2020 roku
glob.iglob(path/**, recursive=True)
wydaje się najbardziej pytonicznym rozwiązaniem, czyli:Wynik:
Uwagi:
1 - glob.iglob
2 - Jeśli rekurencja to
True
, wzorzec'**'
będzie pasował do wszystkich plików i zera lub więcejdirectories
isubdirectories
.3 - Jeśli katalog zawiera pliki zaczynające się od,
.
nie będą one domyślnie dopasowywane. Na przykład rozważmy katalog zawierającycard.gif
i.card.gif
:4 - Możesz również użyć
rglob(pattern)
, co jest tym samym, co wywołanieglob()
z**/
dodaniem przed podanym wzorcem względnym.źródło