Come elencare solo le directory di livello superiore in Python?
-
02-07-2019 - |
Domanda
Voglio essere in grado di elencare solo le directory all'interno di alcune cartelle. Questo significa che non voglio elencare i nomi dei file, né voglio sottocartelle aggiuntive.
Vediamo se un esempio aiuta. Nella directory corrente abbiamo:
>>> os.listdir(os.getcwd())
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'mod_p
ython-wininst.log', 'NEWS.txt', 'pymssql-wininst.log', 'python.exe', 'pythonw.ex
e', 'README.txt', 'Removemod_python.exe', 'Removepymssql.exe', 'Scripts', 'tcl',
'Tools', 'w9xpopen.exe']
Tuttavia, non voglio elencare i nomi dei file. Né voglio sottocartelle come \ Lib \ curses. Essenzialmente quello che voglio funziona con quanto segue:
>>> for root, dirnames, filenames in os.walk('.'):
... print dirnames
... break
...
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'Scripts', 'tcl', 'Tools']
Tuttavia, mi chiedo se esiste un modo più semplice per ottenere gli stessi risultati. Ho l'impressione che l'utilizzo di os.walk solo per restituire il livello superiore sia inefficiente / troppo.
Soluzione
Filtra il risultato usando os.path.isdir () (e usa os.path.join () per ottenere il percorso reale):
>>> [ name for name in os.listdir(thedir) if os.path.isdir(os.path.join(thedir, name)) ]
['ctypes', 'distutils', 'encodings', 'lib-tk', 'config', 'idlelib', 'xml', 'bsddb', 'hotshot', 'logging', 'doc', 'test', 'compiler', 'curses', 'site-packages', 'email', 'sqlite3', 'lib-dynload', 'wsgiref', 'plat-linux2', 'plat-mac']
Altri suggerimenti
os.walk
Usa os.walk
con next
funzione elemento:
next(os.walk('.'))[1]
Per Python < = 2.5 usa:
os.walk('.').next()[1]
Come funziona
[1]
è un generatore e chiamando dirnames
otterrà il primo risultato sotto forma di una 3 tupla (dirpath, dirnames, nomi di file). Pertanto l'indice <=> restituisce solo il <=> da quella tupla.
Filtra l'elenco usando os.path.isdir per rilevare le directory.
filter(os.path.isdir, os.listdir(os.getcwd()))
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
Nota che, anziché fare os.listdir(os.getcwd())
, è preferibile fare os.listdir(os.path.curdir)
. Una chiamata di funzione in meno ed è portatile.
Quindi, per completare la risposta, per ottenere un elenco di directory in una cartella:
def listdirs(folder):
return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
Se preferisci i percorsi completi, usa questa funzione:
def listdirs(folder):
return [
d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
if os.path.isdir(d)
]
Solo per aggiungere che l'uso di os.listdir () non " richiede molta elaborazione e os.walk (). molto semplice () [1] " . Questo perché os.walk () utilizza os.listdir () internamente. In effetti se li provi insieme:
>>>> import timeit
>>>> timeit.timeit("os.walk('.').next()[1]", "import os", number=10000)
1.1215229034423828
>>>> timeit.timeit("[ name for name in os.listdir('.') if os.path.isdir(os.path.join('.', name)) ]", "import os", number=10000)
1.0592019557952881
Il filtraggio di os.listdir () è leggermente più veloce.
Un modo molto più semplice ed elegante è usare questo:
import os
dir_list = os.walk('.').next()[1]
print dir_list
Esegui questo script nella stessa cartella per cui desideri i nomi delle cartelle. Ti darà esattamente solo il nome delle cartelle immediate (anche quello senza il percorso completo delle cartelle).
Anche questo sembra funzionare (almeno su Linux):
import glob, os
glob.glob('*' + os.path.sep)
essendo un principiante qui non posso ancora commentare direttamente, ma ecco una piccola correzione che vorrei aggiungere alla parte seguente di <> # 932;! <> # 918;! <> # 937;! <> # 932;!! <> # 918 ; & # 921; & # 927; & # 933; risposta di :
Se preferisci i percorsi completi, usa questa funzione:
def listdirs(folder): return [ d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder)) if os.path.isdir(d) ]
per quelli ancora su Python < 2.4 : il costrutto interno deve essere un elenco anziché una tupla e quindi dovrebbe essere letto in questo modo:
def listdirs(folder):
return [
d for d in [os.path.join(folder, d1) for d1 in os.listdir(folder)]
if os.path.isdir(d)
]
altrimenti si ottiene un errore di sintassi.
Utilizzando la comprensione dell'elenco,
[a for a in os.listdir() if os.path.isdir(a)]
Penso che sia il modo più semplice
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]
Per un elenco di nomi di percorsi completi preferisco questa versione alle altre soluzioni qui:
def listdirs(dir):
return [os.path.join(os.path.join(dir, x)) for x in os.listdir(dir)
if os.path.isdir(os.path.join(dir, x))]
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]
Un'opzione più sicura che non fallisce quando non c'è directory.
def listdirs(folder):
if os.path.exists(folder):
return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
else:
return []
Ti piace?
>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]
-- This will exclude files and traverse through 1 level of sub folders in the root
def list_files(dir):
List = []
filterstr = ' '
for root, dirs, files in os.walk(dir, topdown = True):
#r.append(root)
if (root == dir):
pass
elif filterstr in root:
#filterstr = ' '
pass
else:
filterstr = root
#print(root)
for name in files:
print(root)
print(dirs)
List.append(os.path.join(root,name))
#print(os.path.join(root,name),"\n")
print(List,"\n")
return List