Pracuję nad skryptem, który będzie rekurencyjnie przechodził przez podfoldery w głównym folderze i budował listę z określonego typu plików. Mam problem ze skryptem. Obecnie jest ustawiony w następujący sposób
for root, subFolder, files in os.walk(PATH):
for item in files:
if item.endswith(".txt") :
fileNamePath = str(os.path.join(root,subFolder,item))
problem polega na tym, że zmienna subFolder pobiera listę podfolderów, a nie folder, w którym znajduje się plik ITEM. Myślałem o uruchomieniu pętli for dla podfolderu wcześniej i dołączeniu do pierwszej części ścieżki, ale pomyślałem, że dwukrotnie sprawdzę, czy ktoś ma wcześniej jakieś sugestie. Dzięki za pomoc!
rglob
jest niewrażliwy na platformach Windows - ale nie jest przenośny nieczuły.glob
też z (Python 3.6 tutaj):glob.iglob(os.path.join(real_source_path, '**', '*.[xX][mM][lL]')
iglob
nie działa dla plików w podfolderach lub niższych. Musisz dodaćrecursive=True
.glob.glob()
otrzymał nowy parametr rekurencyjny .Jeśli chcesz pobrać każdy
.txt
plik podmy_path
(rekursywnie włączając podkatalogi):Jeśli potrzebujesz iteratora, możesz użyć iglob jako alternatywy:
źródło
files = glob.glob(PATH + '/*/**/*.txt', recursive=True)
?Przetłumaczę rozumienie list Johna La Rooya na zagnieżdżone for, na wypadek gdyby ktoś inny miał problemy ze zrozumieniem.
Powinien być równoważny z:
Oto dokumentacja dotycząca rozumienia list i funkcji os.walk i glob.glob .
źródło
glob.glob(..., recursive=True)
ilist(Path(dir).glob(...'))
nie zrobił.To wydaje się być najszybszym rozwiązaniem mogłem wymyślić, i to szybciej niż
os.walk
i dużo szybciej niż jakiekolwiekglob
rozwiązanie .f.path
naf.name
(nie zmieniaj tego w przypadku podfolderów!).Args:
dir: str, ext: list
.Funkcja zwraca dwie listy:
subfolders, files
.Poniżej znajduje się szczegółowa analiza szybkości.
Analiza prędkości
różne metody pobierania wszystkich plików z określonym rozszerzeniem do wszystkich podfolderów i folderu głównego.
tl; dr:
-
fast_scandir
wyraźnie wygrywa i jest dwa razy szybszy niż wszystkie inne rozwiązania, z wyjątkiem os.walk.-
os.walk
drugie miejsce zajmuje nieco wolniej.- użycie
glob
znacznie spowolni proces.- W żadnym z wyników nie zastosowano naturalnego sortowania . Oznacza to, że wyniki będą sortowane w następujący sposób: 1, 10, 2. Aby uzyskać naturalne sortowanie (1, 2, 10), spójrz na https://stackoverflow.com/a/48030307/2441026
Wyniki:
Testy zostały wykonane z W7x64, Python 3.8.1, 20 uruchomień. 16596 plików w 439 (częściowo zagnieżdżonych) podfolderach.
find_files
pochodzi z https://stackoverflow.com/a/45646357/2441026 i umożliwia wyszukiwanie kilku rozszerzeń.fast_scandir
został napisany przeze mnie i zwróci również listę podfolderów. Możesz dać mu listę rozszerzeń do wyszukania (testowałem listę z jednym wpisem na prostąif ... == ".jpg"
i nie było znaczącej różnicy).źródło
Nowa
pathlib
biblioteka upraszcza to do jednej linii:Możesz także skorzystać z wersji generatora:
Zwraca to
Path
obiekty, których możesz użyć do prawie wszystkiego lub pobrać nazwę pliku jako ciąg znakówfile.name
.źródło
To nie jest najbardziej pythonowa odpowiedź, ale umieszczę ją tutaj dla zabawy, ponieważ jest to zgrabna lekcja rekurencji
Na moim komputerze mam dwa foldery
root
iroot2
Powiedzmy, że chcemy znaleźć wszystkie
.txt
i wszystkie.mid
pliki w jednym z tych katalogów, to mogę po prostu zrobićźródło
Cykliczne jest nowością w Pythonie 3.5, więc nie będzie działać w Pythonie 2.7. Oto przykład, który używa
r
ciągów, więc wystarczy podać ścieżkę taką, jaka jest w Win, Lin, ...Uwaga: wyświetli listę wszystkich plików, bez względu na to, jak głęboko powinny się znaleźć.
źródło
Możesz to zrobić w ten sposób, aby zwrócić listę plików ze ścieżkami bezwzględnymi.
źródło
Jeśli nie masz nic przeciwko zainstalowaniu dodatkowej biblioteki świateł, możesz to zrobić:
Stosowanie:
Wynik powinien wyglądać mniej więcej tak:
Działa na Pythonie 2.7 i Pythonie 3.
Github: https://github.com/kyzas/plazy#list-files
Zastrzeżenie: jestem autorem
plazy
.źródło
Ta funkcja rekurencyjnie umieszcza tylko pliki na liście. Mam nadzieję, że tak będzie.
źródło
Twoje oryginalne rozwiązanie było prawie poprawne, ale zmienna „root” jest dynamicznie aktualizowana, gdy rekurencyjnie przechodzi dookoła. os.walk () jest generatorem rekurencyjnym. Każdy zestaw krotek (katalog główny, podfolder, pliki) jest przeznaczony dla określonego katalogu głównego, zgodnie z konfiguracją.
to znaczy
Dokonałem drobnych poprawek w Twoim kodzie, aby wydrukować pełną listę.
Mam nadzieję że to pomoże!
źródło