¿Hay alguna manera de devolver una lista de todos los subdirectorios en el directorio actual en Python?
Sé que puedes hacer esto con archivos, pero necesito obtener la lista de directorios en su lugar.
¿Hay alguna manera de devolver una lista de todos los subdirectorios en el directorio actual en Python?
Sé que puedes hacer esto con archivos, pero necesito obtener la lista de directorios en su lugar.
Respuestas:
¿Te refieres a subdirectorios inmediatos, o cada directorio en el árbol?
De cualquier manera, podría usar os.walk
para hacer esto:
os.walk(directory)
producirá una tupla para cada subdirectorio. La primera entrada en la 3-tupla es un nombre de directorio, entonces
[x[0] for x in os.walk(directory)]
debería darle todos los subdirectorios, de forma recursiva.
Tenga en cuenta que la segunda entrada en la tupla es la lista de directorios secundarios de la entrada en la primera posición, por lo que podría usar esto en su lugar, pero no es probable que le ahorre mucho.
Sin embargo, puede usarlo solo para darle los directorios secundarios inmediatos:
next(os.walk('.'))[1]
O vea las otras soluciones ya publicadas, utilizando os.listdir
e os.path.isdir
, incluidas las de " Cómo obtener todos los subdirectorios inmediatos en Python ".
os.walk('.').next()[1]
o os.walk('.').__next__()[1]
directamente. En su lugar, use la función incorporada next()
, que está disponible tanto en Python 2 (consulte el documento) como en Python 3 (consulte el documento) . Por ejemplo: next(os.walk('.'))[1]
.
os.walk('.').next()[1]
directamente?
iteraror.__next__()
es un método interno y el iterator.next()
uso debe pasar a la versión incorporada de next()
acuerdo con PEP-3114. Ver PEP-3114 que fue aprobado en 2007.
os.walk
y os.listdir
+ os.path.isdir
soluciones: acabo de probar en un directorio con 10,000 subdirectorios (con millones de archivos en la jerarquía a continuación) y las diferencias de rendimiento son insignificantes. os.walk
: "10 bucles, mejor de 3: 44,6 ms por bucle" y os.listdir
+ os.path.isdir
: "10 bucles, mejor de 3: 45,1 ms por bucle"
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
encendido o
para obtener el camino completo, de lo contrario isdir(0)
siempre devolverá falso
os.path.join
dos veces, primero puede unirse y luego filtrar la lista usando os.path.isdir
: filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
Podrías usar glob.glob
from glob import glob
glob("/path/to/directory/*/")
No olvides el final /
después del *
.
/
en los nombres
/
que es el separador de carpetas, haga lo siguiente:glob(os.path.join(path_to_directory, "*", ""))
recursive=True
Mucho mejor que lo anterior, ya que no necesita varios os.path.join () y obtendrá la ruta completa directamente (si lo desea), puede hacerlo en Python 3.5 y superior.
subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]
Esto le dará la ruta completa al subdirectorio. Si solo desea el nombre del subdirectorio, use en f.name
lugar def.path
https://docs.python.org/3/library/os.html#os.scandir
Ligeramente OT: en caso de que necesite todas las subcarpetas recursivamente y / o todos los archivos recursivamente , eche un vistazo a esta función, que es más rápida que os.walk
& glob
y devolverá una lista de todas las subcarpetas, así como todos los archivos dentro de esas (sub) subcarpetas: https://stackoverflow.com/a/59803793/2441026
En caso de que desee solo todas las subcarpetas de forma recursiva :
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
Devuelve una lista de todas las subcarpetas con sus rutas completas. De nuevo, esto es más rápido que os.walk
y mucho más rápido que glob
.
Un análisis de todas las funciones.
tl; dr:
- Si desea obtener todos los subdirectorios inmediatos para un uso de carpeta os.scandir
.
- Si desea obtener todos los subdirectorios, incluso los anidados , use os.walk
o, un poco más rápido, la fast_scandir
función anterior.
- Nunca lo use os.walk
solo para subdirectorios de nivel superior, ya que puede ser cientos (!) De veces más lento que os.scandir
.
os.walk
será la carpeta base. Por lo tanto, no obtendrá solo subdirectorios. Puedes usar fu.pop(0)
para eliminarlo.Resultados :
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
Probado 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()
Si necesita una solución recursiva que encuentre todos los subdirectorios en los subdirectorios, use walk como se propuso anteriormente.
Si solo necesita los directorios secundarios del directorio actual, combine os.listdir
conos.path.isdir
Prefiero usar filter ( https://docs.python.org/2/library/functions.html#filter ), pero esto es solo cuestión de gustos.
d='.'
filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d))
Implementado esto 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)
Puede obtener la lista de subdirectorios (y archivos) en Python 2.7 usando os.listdir (ruta)
import os
os.listdir(path) # list of subdirectories and files
os.listdir
listas de contenido del directorio, incluidos los archivos.
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 introdujo el pathlib
módulo en la biblioteca estándar, que proporciona un enfoque orientado a objetos para manejar rutas del sistema de archivos:
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 también está disponible en Python 2.7 a través del módulo pathlib2 en PyPi.
for f in filter(Path.is_dir, p.iterdir()):
Como me topé con este problema usando las rutas Python 3.4 y Windows UNC, aquí hay una variante para este entorno:
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 es nuevo en Python 3.4 y hace que trabajar con rutas en diferentes sistemas operativos sea mucho más fácil: https://docs.python.org/3.4/library/pathlib.html
Aunque esta pregunta fue respondida hace mucho tiempo. Quiero recomendar el uso del pathlib
módulo, ya que esta es una forma sólida de trabajar en Windows y Unix OS.
Entonces, para obtener todas las rutas en un directorio específico, incluidos los subdirectorios:
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
etc.
Gracias por los consejos chicos. Me encontré con un problema con los enlaces suaves (recursión infinita) que se devuelven como directorios. Softlinks? ¡No queremos enlaces apestosos! Entonces...
Esto representaba solo los directorios, no los enlaces suaves:
>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
[x[0] for x in inf]
llama en python para poder buscarlo?
Copiar y pegar amigable en ipython
:
import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))
Salida de print(folders)
:
['folderA', 'folderB']
x
es el elemento de la lista creada por os.listdir(d)
porque listdir
devolverá los archivos y carpetas con los que está usando el filter
comando os.path.isdir
para filtrar los archivos de la lista.
Así es como lo hago.
import os
for x in os.listdir(os.getcwd()):
if os.path.isdir(x):
print(x)
Aquí hay un par de funciones simples basadas en el ejemplo de @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]
Basándose en la solución de Eli Bendersky, use el siguiente ejemplo:
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"
¿Dónde <your_directory>
está la ruta al directorio que desea recorrer?
Esta respuesta ya no parece existir.
directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]
Recientemente tuve una pregunta similar y descubrí que la mejor respuesta para python 3.6 (como agregó el usuario havlock) es usarla os.scandir
. Como parece que no hay solución para usarlo, agregaré la mía. Primero, una solución no recursiva que enumera solo los subdirectorios directamente bajo el directorio raíz.
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 versión recursiva se vería así:
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
tenga en cuenta que entry.path
maneja la ruta absoluta al subdirectorio. En caso de que solo necesite el nombre de la carpeta, puede usar entry.name
en su lugar. Consulte os.DirEntry para obtener detalles adicionales sobre el entry
objeto.
usar una función de filtro os.path.isdir
sobre os.listdir()
algo como estofilter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])
Esto mostrará una lista de todos los subdirectorios en el árbol de archivos.
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
es nuevo en la versión 3.4
Función para devolver una lista de todos los subdirectorios dentro de una ruta de archivo determinada. Buscará en todo el árbol de archivos.
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
podemos obtener una lista de todas las carpetas usando os.walk ()
import os
path = os.getcwd()
pathObject = os.walk(path)
este pathObject es un objeto y podemos obtener una matriz por
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]) ....]
Podemos obtener una lista de todos los subdirectorios iterando a través del arr e imprimiendo la matriz del medio
for i in arr:
for j in i[1]:
print(j)
Esto imprimirá todo el subdirectorio.
Para obtener todos los archivos:
for i in arr:
for j in i[2]:
print(i[0] + "/" + j)
Esta función, con un padre dado, directory
itera sobre todo su directories
recursividad y prints
todo filenames
lo que encuentra dentro. Demasiado útil
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 ;")
Al unir varias soluciones desde aquí, esto es lo que terminé usando:
import os
import glob
def list_dirs(path):
return [os.path.basename(x) for x in filter(
os.path.isdir, glob.glob(os.path.join(path, '*')))]