C'è un modo per restituire un elenco di tutte le sottodirectory nella directory corrente in Python?
So che puoi farlo con i file, ma invece devo ottenere l'elenco delle directory.
C'è un modo per restituire un elenco di tutte le sottodirectory nella directory corrente in Python?
So che puoi farlo con i file, ma invece devo ottenere l'elenco delle directory.
Risposte:
Intendi le sottodirectory immediate o ogni directory in fondo all'albero?
In entrambi i casi, è possibile utilizzare os.walk
per fare questo:
os.walk(directory)
produrrà una tupla per ogni sottodirectory. La prima voce nella 3-tupla è un nome di directory, quindi
[x[0] for x in os.walk(directory)]
dovrebbe darti tutte le sottodirectory, in modo ricorsivo.
Nota che la seconda voce nella tupla è la lista delle directory secondarie della voce nella prima posizione, quindi puoi usarla invece, ma non è probabile che ti salvi molto.
Tuttavia, potresti usarlo solo per darti le directory secondarie immediate:
next(os.walk('.'))[1]
Oppure vedi le altre soluzioni già pubblicate, usando os.listdir
e os.path.isdir
, comprese quelle in " Come ottenere tutte le sottodirectory immediate in Python ".
os.walk('.').next()[1]
o os.walk('.').__next__()[1]
direttamente. Invece, usa la funzione integrata next()
, che è disponibile sia in Python 2 (vedi doc) che in Python 3 (vedi doc) . Ad esempio: next(os.walk('.'))[1]
.
os.walk('.').next()[1]
direttamente?
iteraror.__next__()
è un metodo interno e l' iterator.next()
utilizzo dovrebbe essere trasferito nell'integrato next()
secondo PEP-3114. Vedi PEP-3114 che è stato approvato nel 2007.
os.walk
e os.listdir
+ os.path.isdir
soluzioni: ho appena testato su una directory con 10.000 sottodirectory (con milioni di file nella gerarchia di seguito) e le differenze di prestazioni sono trascurabili. os.walk
: "10 loop, meglio di 3: 44.6 msec per loop" e os.listdir
+ os.path.isdir
: "10 loop, meglio di 3: 45.1 msec per loop"
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
on o
per ottenere il percorso completo, altrimenti isdir(0)
tornerà sempre falso
os.path.join
due volte, puoi prima unirti e poi filtrare l'elenco usando os.path.isdir
: filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
Potresti semplicemente usare glob.glob
from glob import glob
glob("/path/to/directory/*/")
Non dimenticare il finale /
dopo il *
.
/
nei nomi
/
di essere il separatore di cartelle, procedi come segue:glob(os.path.join(path_to_directory, "*", ""))
recursive=True
Molto più bello di quanto sopra, perché non hai bisogno di diversi os.path.join () e otterrai il percorso completo direttamente (se lo desideri), puoi farlo in Python 3.5 e versioni successive.
subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]
Ciò fornirà il percorso completo alla sottodirectory. Se vuoi solo il nome della sottodirectory usa f.name
invece dif.path
https://docs.python.org/3/library/os.html#os.scandir
Leggermente OT: Nel caso in cui avete bisogno di tutte le sottocartelle in modo ricorsivo e / o tutti i file in modo ricorsivo , hanno uno sguardo a questa funzione, che è più veloce di os.walk
& glob
e restituirà un elenco di tutte le sottocartelle e tutti i file all'interno di queste (sotto) sottocartelle: https://stackoverflow.com/a/59803793/2441026
Nel caso in cui si desideri ricorsivamente solo tutte le sottocartelle :
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
Restituisce un elenco di tutte le sottocartelle con i loro percorsi completi. Questo è ancora più veloce di os.walk
e molto più veloce di glob
.
Un'analisi di tutte le funzioni
tl; dr:
- Se vuoi ottenere tutte le sottodirectory immediate per una cartella, usa os.scandir
.
- Se vuoi ottenere tutte le sottodirectory, anche quelle nidificate , usa os.walk
o - leggermente più veloce - la fast_scandir
funzione sopra.
- Non utilizzare mai os.walk
solo per le sottodirectory di livello superiore, poiché può essere centinaia (!) Volte più lenta di os.scandir
.
os.walk
sarà la cartella di base. Quindi non otterrai solo le sottodirectory. Puoi usarlo fu.pop(0)
per rimuoverlo.Risultati :
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
Testato con 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()
Se hai bisogno di una soluzione ricorsiva che troverà tutte le sottodirectory nelle sottodirectory, usa walk come proposto prima.
Se hai solo bisogno delle directory figlio della directory corrente, combinale os.listdir
conos.path.isdir
Preferisco usare il filtro ( https://docs.python.org/2/library/functions.html#filter ), ma questa è solo una questione di gusti.
d='.'
filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d))
Implementato usando 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)
Puoi ottenere l'elenco delle sottodirectory (e dei file) in Python 2.7 usando os.listdir (percorso)
import os
os.listdir(path) # list of subdirectories and files
os.listdir
elenca i contenuti della directory inclusi i file.
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 ha introdotto il pathlib
modulo nella libreria standard, che fornisce un approccio orientato agli oggetti per gestire i percorsi del filesystem:
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 è disponibile anche su Python 2.7 tramite il modulo pathlib2 su PyPi.
for f in filter(Path.is_dir, p.iterdir()):
Dal momento che mi sono imbattuto in questo problema utilizzando i percorsi UNC di Python 3.4 e Windows, ecco una variante per questo ambiente:
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 è una novità di Python 3.4 e semplifica notevolmente l'utilizzo di percorsi con diversi sistemi operativi: https://docs.python.org/3.4/library/pathlib.html
Sebbene questa domanda abbia una risposta molto tempo fa. Voglio raccomandare di usare ilpathlib
modulo poiché questo è un modo affidabile per lavorare su Windows e sistemi operativi Unix.
Quindi, per ottenere tutti i percorsi in una directory specifica comprese le sottodirectory:
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
eccetera.
Grazie per i suggerimenti, ragazzi. Ho riscontrato un problema con i softlink (ricorsione infinita) che venivano restituiti come dir. Softlink? Non vogliamo collegamenti soft puzzolenti! Così...
Questo ha reso solo le directory, non i softlink:
>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
[x[0] for x in inf]
chiamato in Python in modo che io possa cercarlo?
Copia incolla amichevole in ipython
:
import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))
Uscita da print(folders)
:
['folderA', 'folderB']
x
è l'elemento dall'elenco creato da os.listdir(d)
perché listdir
restituirà i file e le cartelle con cui sta usando il filter
comando os.path.isdir
per filtrare tutti i file dall'elenco.
Questo è come lo faccio.
import os
for x in os.listdir(os.getcwd()):
if os.path.isdir(x):
print(x)
Ecco un paio di semplici funzioni basate sull'esempio di @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]
Basandosi sulla soluzione di Eli Bendersky, utilizzare il seguente esempio:
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"
dove si <your_directory>
trova il percorso della directory che si desidera attraversare.
Questa risposta non sembra esistere già.
directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]
Di recente ho fatto una domanda simile e ho scoperto che la migliore risposta per python 3.6 (come ha aggiunto l'havlock dell'utente) è usare os.scandir
. Dal momento che sembra che non ci sia soluzione usando, aggiungerò il mio. Innanzitutto, una soluzione non ricorsiva che elenca solo le sottodirectory direttamente nella directory principale.
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
La versione ricorsiva sarebbe simile a questa:
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
tieni presente che entry.path
esercita il percorso assoluto verso la sottodirectory. Nel caso in cui sia necessario solo il nome della cartella, è possibile utilizzare entry.name
invece. Fare riferimento a os.DirEntry per ulteriori dettagli entry
sull'oggetto.
usa una funzione di filtro os.path.isdir
su os.listdir()
qualcosa del generefilter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])
Questo elencherà tutte le sottodirectory lungo l'albero dei file.
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
è nuovo nella versione 3.4
Funzione per restituire un elenco di tutte le sottodirectory all'interno di un determinato percorso di file. Cercherà attraverso l'intero albero dei file.
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
possiamo ottenere l'elenco di tutte le cartelle utilizzando os.walk ()
import os
path = os.getcwd()
pathObject = os.walk(path)
this pathObject è un oggetto e possiamo ottenere un array da
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]) ....]
Siamo in grado di ottenere l'elenco di tutta la sottodirectory ripetendo l' arr e stampando l'array centrale
for i in arr:
for j in i[1]:
print(j)
Questo stamperà tutta la sottodirectory.
Per ottenere tutti i file:
for i in arr:
for j in i[2]:
print(i[0] + "/" + j)
Questa funzione, con un determinato genitore, directory
scorre su tutto il suo directories
modo ricorsivo e prints
tutto filenames
ciò che trova all'interno. Troppo utile.
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 ;")