Czy istnieje sposób na zwrócenie listy wszystkich podkatalogów w bieżącym katalogu w Pythonie?
Wiem, że możesz to zrobić za pomocą plików, ale zamiast tego muszę uzyskać listę katalogów.
Czy istnieje sposób na zwrócenie listy wszystkich podkatalogów w bieżącym katalogu w Pythonie?
Wiem, że możesz to zrobić za pomocą plików, ale zamiast tego muszę uzyskać listę katalogów.
Odpowiedzi:
Masz na myśli bezpośrednie podkatalogi, czy każdy katalog bezpośrednio w drzewie?
Tak czy inaczej, możesz to os.walk
zrobić:
os.walk(directory)
da krotkę dla każdego podkatalogu. Pierwszym wpisem w 3-krotce jest nazwa katalogu, więc
[x[0] for x in os.walk(directory)]
powinien rekurencyjnie dać ci wszystkie podkatalogi.
Zauważ, że drugi wpis w krotce to lista katalogów potomnych wpisu na pierwszej pozycji, więc możesz użyć tego zamiast tego, ale raczej nie zaoszczędzisz dużo.
Jednak możesz go użyć tylko po to, aby dać ci bezpośrednie katalogi potomne:
next(os.walk('.'))[1]
Lub zobacz inne opublikowane już rozwiązania, wykorzystujące os.listdir
i os.path.isdir
, w tym te z „ Jak uzyskać wszystkie bezpośrednie podkatalogi w Pythonie ”.
os.walk('.').next()[1]
ani os.walk('.').__next__()[1]
bezpośrednio. Zamiast tego użyj wbudowanej funkcji next()
, która jest dostępna zarówno w Pythonie 2 (patrz dokument), jak i Python 3 (patrz dokument) . Na przykład: next(os.walk('.'))[1]
.
os.walk('.').next()[1]
bezpośrednio?
iteraror.__next__()
jest to metoda wewnętrzna, a iterator.next()
użycie należy przenieść do wbudowanego next()
zgodnie z PEP-3114. Zobacz PEP-3114, który został zatwierdzony w 2007 r.
os.walk
i os.listdir
+ os.path.isdir
rozwiązań: Właśnie testowany na katalogu z 10.000 podkatalogów (z milionów plików w hierarchii poniżej), a różnice w wynikach są znikome. os.walk
: „10 pętli, najlepiej 3: 44,6 ms na pętlę” i os.listdir
+ os.path.isdir
: „10 pętli, najlepiej 3: 45,1 ms na pętlę”
import os
d = '.'
[os.path.join(d, o) for o in os.listdir(d)
if os.path.isdir(os.path.join(d,o))]
os.path.join
na o
uzyskać pełną ścieżkę, inaczej isdir(0)
będzie zawsze return false
os.path.join
podwójnego dzwonienia , możesz najpierw dołączyć, a następnie przefiltrować listę, używając os.path.isdir
: filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
Możesz po prostu użyć glob.glob
from glob import glob
glob("/path/to/directory/*/")
Nie zapomnij o zakończeniu /
po *
.
/
w nazwach
/
że to separator folderów, zrób to:glob(os.path.join(path_to_directory, "*", ""))
recursive=True
O wiele ładniejsze niż powyższe, ponieważ nie potrzebujesz kilku os.path.join () i otrzymasz pełną ścieżkę bezpośrednio (jeśli chcesz), możesz to zrobić w Pythonie 3.5 i nowszych.
subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]
To da pełną ścieżkę do podkatalogu. Jeśli chcesz tylko użyć nazwy podkatalogu f.name
zamiastf.path
https://docs.python.org/3/library/os.html#os.scandir
Nieznacznie OT: Jeśli potrzebujesz rekursywnie wszystkich podfolderów i / lub wszystkich plików , spójrz na tę funkcję, która jest szybsza niż os.walk
& glob
i zwróci listę wszystkich podfolderów, a także wszystkich plików w tych (pod-) podfolderach: https://stackoverflow.com/a/59803793/2441026
Jeśli chcesz rekurencyjnie tylko wszystkich podfolderów :
def fast_scandir(dirname):
subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()]
for dirname in list(subfolders):
subfolders.extend(fast_scandir(dirname))
return subfolders
Zwraca listę wszystkich podfolderów wraz z ich pełnymi ścieżkami. To znowu jest szybsze os.walk
i dużo szybsze niż glob
.
Analiza wszystkich funkcji
tl; dr:
- Jeśli chcesz uzyskać wszystkie bezpośrednie podkatalogi do wykorzystania w folderze os.scandir
.
- Jeśli chcesz uzyskać wszystkie podkatalogi, nawet zagnieżdżone , użyj os.walk
lub - nieco szybciej - fast_scandir
powyższej funkcji.
- Nigdy nie używaj os.walk
tylko podkatalogów najwyższego poziomu, ponieważ mogą być setki (!) Razy wolniejsze niż os.scandir
.
os.walk
będzie folder podstawowy. Więc nie dostaniesz tylko podkatalogów. Możesz go użyć fu.pop(0)
do usunięcia.Wyniki :
os.scandir took 1 ms. Found dirs: 439
os.walk took 463 ms. Found dirs: 441 -> it found the nested one + base folder.
glob.glob took 20 ms. Found dirs: 439
pathlib.iterdir took 18 ms. Found dirs: 439
os.listdir took 18 ms. Found dirs: 439
Testowane z W7x64, Python 3.8.1.
# -*- coding: utf-8 -*-
# Python 3
import time
import os
from glob import glob
from pathlib import Path
directory = r"<insert_folder>"
RUNS = 1
def run_os_walk():
a = time.time_ns()
for i in range(RUNS):
fu = [x[0] for x in os.walk(directory)]
print(f"os.walk\t\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_glob():
a = time.time_ns()
for i in range(RUNS):
fu = glob(directory + "/*/")
print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_pathlib_iterdir():
a = time.time_ns()
for i in range(RUNS):
dirname = Path(directory)
fu = [f for f in dirname.iterdir() if f.is_dir()]
print(f"pathlib.iterdir\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_os_listdir():
a = time.time_ns()
for i in range(RUNS):
dirname = Path(directory)
fu = [os.path.join(directory, o) for o in os.listdir(directory) if os.path.isdir(os.path.join(directory, o))]
print(f"os.listdir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_os_scandir():
a = time.time_ns()
for i in range(RUNS):
fu = [f.path for f in os.scandir(directory) if f.is_dir()]
print(f"os.scandir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms.\tFound dirs: {len(fu)}")
if __name__ == '__main__':
run_os_scandir()
run_os_walk()
run_glob()
run_pathlib_iterdir()
run_os_listdir()
Jeśli potrzebujesz rozwiązania rekurencyjnego, które znajdzie wszystkie podkatalogi w podkatalogach, skorzystaj z marszu zgodnie z wcześniejszą propozycją.
Jeśli potrzebujesz tylko katalogów potomnych bieżącego katalogu, połącz os.listdir
zos.path.isdir
Wolę używać filtra ( https://docs.python.org/2/library/functions.html#filter ), ale to tylko kwestia gustu.
d='.'
filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d))
Zaimplementowano to za pomocą python-os-walk. ( http://www.pythonforbeginners.com/code-snippets-source-code/python-os-walk/ )
import os
print("root prints out directories only from what you specified")
print("dirs prints out sub-directories from root")
print("files prints out all files from root and directories")
print("*" * 20)
for root, dirs, files in os.walk("/var/log"):
print(root)
print(dirs)
print(files)
Możesz uzyskać listę podkatalogów (i plików) w Pythonie 2.7, używając os.listdir (ścieżka)
import os
os.listdir(path) # list of subdirectories and files
os.listdir
zawiera listę zawartości katalogu, w tym plików.
print("\nWe are listing out only the directories in current directory -")
directories_in_curdir = filter(os.path.isdir, os.listdir(os.curdir))
print(directories_in_curdir)
files = filter(os.path.isfile, os.listdir(os.curdir))
print("\nThe following are the list of all files in the current directory -")
print(files)
Python 3.4 wprowadziła ten pathlib
moduł do standardowej biblioteki, która zapewnia podejścia obiektowego do ścieżek uchwyt systemu plików:
from pathlib import Path
p = Path('./')
# List comprehension
[f for f in p.iterdir() if f.is_dir()]
# The trailing slash to glob indicated directories
# This will also include the current directory '.'
list(p.glob('**/'))
Pathlib jest również dostępny w Pythonie 2.7 za pośrednictwem modułu pathlib2 w PyPi.
for f in filter(Path.is_dir, p.iterdir()):
Ponieważ natknąłem się na ten problem przy użyciu ścieżek Python 3.4 i Windows UNC, oto wariant tego środowiska:
from pathlib import WindowsPath
def SubDirPath (d):
return [f for f in d.iterdir() if f.is_dir()]
subdirs = SubDirPath(WindowsPath(r'\\file01.acme.local\home$'))
print(subdirs)
Pathlib jest nowością w Pythonie 3.4 i znacznie ułatwia pracę ze ścieżkami w różnych systemach operacyjnych: https://docs.python.org/3.4/library/pathlib.html
Chociaż na to pytanie dawno już udzielono odpowiedzi. Chcę polecić korzystanie zpathlib
modułu, ponieważ jest to niezawodny sposób pracy w systemach operacyjnych Windows i Unix.
Aby uzyskać wszystkie ścieżki w określonym katalogu, w tym w podkatalogach:
from pathlib import Path
paths = list(Path('myhomefolder', 'folder').glob('**/*.txt'))
# all sorts of operations
file = paths[0]
file.name
file.stem
file.parent
file.suffix
itp.
Dzięki za wskazówki, chłopaki. Wystąpił problem polegający na tym, że softlinks (nieskończona rekurencja) był zwracany jako reż. Softlinks? Nie chcemy żadnych śmierdzących miękkich linków! Więc...
To renderowało tylko katalogi, a nie linki miękkie:
>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
[x[0] for x in inf]
nazywa się Python, abym mógł to sprawdzić?
Kopiuj wklej przyjazny w ipython
:
import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))
Wyjście z print(folders)
:
['folderA', 'folderB']
x
jest pozycją z listy utworzonej przez, os.listdir(d)
ponieważ listdir
zwróci pliki i foldery, których używa filter
polecenia, os.path.isdir
aby odfiltrować dowolne pliki z listy.
Tak to robię.
import os
for x in os.listdir(os.getcwd()):
if os.path.isdir(x):
print(x)
Oto kilka prostych funkcji opartych na przykładzie @Blair Conrad -
import os
def get_subdirs(dir):
"Get a list of immediate subdirectories"
return next(os.walk(dir))[1]
def get_subfiles(dir):
"Get a list of immediate subfiles"
return next(os.walk(dir))[2]
Opierając się na rozwiązaniu Eli Benderskiego, skorzystaj z następującego przykładu:
import os
test_directory = <your_directory>
for child in os.listdir(test_directory):
test_path = os.path.join(test_directory, child)
if os.path.isdir(test_path):
print test_path
# Do stuff to the directory "test_path"
gdzie <your_directory>
jest ścieżka do katalogu, który chcesz przejść.
Ta odpowiedź chyba jeszcze nie istniała.
directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]
Ostatnio miałem podobne pytanie i dowiedziałem się, że najlepszą odpowiedzią na python 3.6 (jak dodał użytkownik havlock) jest użycie os.scandir
. Ponieważ wydaje się, że nie ma rozwiązania, które go wykorzysta, dodam własne. Po pierwsze, nierekurencyjne rozwiązanie, które wyświetla tylko podkatalogi bezpośrednio w katalogu głównym.
def get_dirlist(rootdir):
dirlist = []
with os.scandir(rootdir) as rit:
for entry in rit:
if not entry.name.startswith('.') and entry.is_dir():
dirlist.append(entry.path)
dirlist.sort() # Optional, in case you want sorted directory names
return dirlist
Wersja rekurencyjna wyglądałaby tak:
def get_dirlist(rootdir):
dirlist = []
with os.scandir(rootdir) as rit:
for entry in rit:
if not entry.name.startswith('.') and entry.is_dir():
dirlist.append(entry.path)
dirlist += get_dirlist(entry.path)
dirlist.sort() # Optional, in case you want sorted directory names
return dirlist
pamiętaj, że prowadzi entry.path
absolutną ścieżkę do podkatalogu. Jeśli potrzebujesz tylko nazwy folderu, możesz użyć entry.name
zamiast tego. Dodatkowe informacje na temat obiektu można znaleźć w os.DirEntryentry
.
użyj funkcji filtrowania os.path.isdir
nad os.listdir()
czymś takimfilter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])
Spowoduje to wyświetlenie wszystkich podkatalogów bezpośrednio w drzewie plików.
import pathlib
def list_dir(dir):
path = pathlib.Path(dir)
dir = []
try:
for item in path.iterdir():
if item.is_dir():
dir.append(item)
dir = dir + list_dir(item)
return dir
except FileNotFoundError:
print('Invalid directory')
pathlib
jest nowy w wersji 3.4
Funkcja zwracająca listę wszystkich podkatalogów w ramach danej ścieżki pliku. Przeszukuje całe drzewo plików.
import os
def get_sub_directory_paths(start_directory, sub_directories):
"""
This method iterates through all subdirectory paths of a given
directory to collect all directory paths.
:param start_directory: The starting directory path.
:param sub_directories: A List that all subdirectory paths will be
stored to.
:return: A List of all sub-directory paths.
"""
for item in os.listdir(start_directory):
full_path = os.path.join(start_directory, item)
if os.path.isdir(full_path):
sub_directories.append(full_path)
# Recursive call to search through all subdirectories.
get_sub_directory_paths(full_path, sub_directories)
return sub_directories
możemy uzyskać listę wszystkich folderów za pomocą os.walk ()
import os
path = os.getcwd()
pathObject = os.walk(path)
ten pathObject jest obiektem i możemy uzyskać tablicę według
arr = [x for x in pathObject]
arr is of type [('current directory', [array of folder in current directory], [files in current directory]),('subdirectory', [array of folder in subdirectory], [files in subdirectory]) ....]
Możemy uzyskać listę wszystkich podkatalogów, iterując przez arr i wypisując środkową tablicę
for i in arr:
for j in i[1]:
print(j)
Spowoduje to wydrukowanie całego podkatalogu.
Aby uzyskać wszystkie pliki:
for i in arr:
for j in i[2]:
print(i[0] + "/" + j)
Ta funkcja, z danym rodzicem, directory
iteruje wszystkie directories
rekurencyjnie i prints
wszystko, filenames
co znajduje w sobie. Zbyt przydatne
import os
def printDirectoryFiles(directory):
for filename in os.listdir(directory):
full_path=os.path.join(directory, filename)
if not os.path.isdir(full_path):
print( full_path + "\n")
def checkFolders(directory):
dir_list = next(os.walk(directory))[1]
#print(dir_list)
for dir in dir_list:
print(dir)
checkFolders(directory +"/"+ dir)
printDirectoryFiles(directory)
main_dir="C:/Users/S0082448/Desktop/carpeta1"
checkFolders(main_dir)
input("Press enter to exit ;")