Existe uma maneira de retornar uma lista de todos os subdiretórios no diretório atual em Python?
Eu sei que você pode fazer isso com arquivos, mas preciso obter a lista de diretórios.
Existe uma maneira de retornar uma lista de todos os subdiretórios no diretório atual em Python?
Eu sei que você pode fazer isso com arquivos, mas preciso obter a lista de diretórios.
Respostas:
Você quer dizer subdiretórios imediatos ou todos os diretórios da árvore?
De qualquer forma, você pode usar os.walk
para fazer isso:
os.walk(directory)
produzirá uma tupla para cada subdiretório. A primeira entrada na 3-tupla é um nome de diretório, portanto
[x[0] for x in os.walk(directory)]
deve fornecer todos os subdiretórios, recursivamente.
Observe que a segunda entrada na tupla é a lista de diretórios filhos da entrada na primeira posição; portanto, você pode usá-la, mas provavelmente não economizará muito.
No entanto, você pode usá-lo apenas para fornecer os diretórios filhos imediatos:
next(os.walk('.'))[1]
Ou veja as outras soluções já postadas, usando os.listdir
e os.path.isdir
, incluindo aquelas em " Como obter todos os subdiretórios imediatos no Python ".
os.walk('.').next()[1]
ou os.walk('.').__next__()[1]
diretamente. Em vez disso, use a função interna next()
, disponível no Python 2 (consulte o documento) e Python 3 (consulte o documento) . Por exemplo: next(os.walk('.'))[1]
.
os.walk('.').next()[1]
diretamente?
iteraror.__next__()
é um método interno e o iterator.next()
uso deve ser transferido para o interno de next()
acordo com o PEP-3114. Veja PEP-3114 que foi aprovado em 2007.
os.walk
e : Acabei de testar em um diretório com 10.000 subdiretórios (com milhões de arquivos na hierarquia abaixo) e as diferenças de desempenho são desprezíveis. : "10 loops, o melhor de 3: 44,6 mseg por loop" e + : "10 loops, o melhor de 3: 45,1 mseg por loop"os.listdir
os.path.isdir
os.walk
os.listdir
os.path.isdir
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
em o
obter o caminho completo, caso contrário, isdir(0)
sempre retornará false
os.path.join
duas vezes, primeiro você pode ingressar e filtrar a lista usando os.path.isdir
: filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
Você poderia apenas usar glob.glob
from glob import glob
glob("/path/to/directory/*/")
Não esqueça o rastro /
após o *
.
/
/
que é o separador de pastas, faça o seguinte:glob(os.path.join(path_to_directory, "*", ""))
recursive=True
Muito melhor do que o acima, porque você não precisa de vários os.path.join () e obterá o caminho completo diretamente (se desejar), você pode fazer isso no Python 3.5 e acima.
subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]
Isso fornecerá o caminho completo para o subdiretório. Se você deseja apenas o nome do subdiretório, use em f.name
vez def.path
https://docs.python.org/3/library/os.html#os.scandir
Ligeiramente OT: Caso você precise de todas as subpastas recursivamente e / ou todos os arquivos recursivamente , observe esta função, que é mais rápida que os.walk
& glob
e retornará uma lista de todas as subpastas, bem como de todos os arquivos dentro dessas (sub) subpastas: https://stackoverflow.com/a/59803793/2441026
Caso você queira apenas todas as subpastas recursivamente :
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
Retorna uma lista de todas as subpastas com seus caminhos completos. Isso novamente é mais rápido que os.walk
e muito mais rápido que glob
.
Uma análise de todas as funções
tl; dr:
- Se você deseja obter todos os subdiretórios imediatos para uma pasta, use os.scandir
.
- Se você deseja obter todos os subdiretórios, mesmo os aninhados , use os.walk
ou - um pouco mais rápido - a fast_scandir
função acima.
- Nunca use os.walk
apenas subdiretórios de nível superior, pois pode ser centenas (!) De vezes mais lento que os.scandir
.
os.walk
será a pasta base. Portanto, você não receberá apenas subdiretórios. Você pode usar fu.pop(0)
para removê-lo.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
Testado com 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 você precisar de uma solução recursiva que encontre todos os subdiretórios nos subdiretórios, use walk como proposto anteriormente.
Se você precisar apenas dos diretórios filhos do diretório atual, combine os.listdir
comos.path.isdir
Prefiro usar o filtro ( https://docs.python.org/2/library/functions.html#filter ), mas isso é apenas uma questão de gosto.
d='.'
filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d))
Implementado isso 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)
Você pode obter a lista de subdiretórios (e arquivos) no Python 2.7 usando os.listdir (caminho)
import os
os.listdir(path) # list of subdirectories and files
os.listdir
lista o conteúdo do diretório, incluindo arquivos.
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)
O Python 3.4 introduziu o pathlib
módulo na biblioteca padrão, que fornece uma abordagem orientada a objetos para lidar com os caminhos do sistema de arquivos:
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('**/'))
O Pathlib também está disponível no Python 2.7 através do módulo pathlib2 no PyPi.
for f in filter(Path.is_dir, p.iterdir()):
Desde que me deparei com esse problema usando caminhos Python 3.4 e Windows UNC, aqui está uma variante para esse 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)
O Pathlib é novo no Python 3.4 e facilita muito o trabalho com caminhos em diferentes sistemas operacionais: https://docs.python.org/3.4/library/pathlib.html
Embora esta pergunta seja respondida há muito tempo. Quero recomendar o uso do pathlib
módulo, pois essa é uma maneira robusta de trabalhar no Windows e no Unix OS.
Portanto, para obter todos os caminhos em um diretório específico, incluindo subdiretórios:
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.
Obrigado pelas dicas, pessoal. Corri um problema com softlinks (recursão infinita) sendo retornados como dirs. Softlinks? Não queremos links fedorentos! Assim...
Isso renderizou apenas os diretórios, não os softlinks:
>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
[x[0] for x in inf]
chamado em python para que eu possa procurar?
Copiar e colar amigável em ipython
:
import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))
Saída de print(folders)
:
['folderA', 'folderB']
x
é o item da lista criada por, os.listdir(d)
pois listdir
retornará arquivos e pastas com os quais ele está usando o filter
comando os.path.isdir
para filtrar todos os arquivos da lista.
É assim que eu faço.
import os
for x in os.listdir(os.getcwd()):
if os.path.isdir(x):
print(x)
Aqui estão algumas funções simples baseadas no exemplo 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]
Com base na solução de Eli Bendersky, use o seguinte exemplo:
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"
Onde <your_directory>
está o caminho para o diretório que você deseja percorrer.
Essa resposta parecia não existir já.
directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]
Recentemente, tive uma pergunta semelhante e descobri que a melhor resposta para o python 3.6 (conforme adicionado pelo usuário) é usar os.scandir
. Como parece que não há solução para usá-lo, vou adicionar o meu. Primeiro, uma solução não recursiva que lista apenas os subdiretórios diretamente no diretório raiz.
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
A versão recursiva ficaria assim:
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
tenha em mente que entry.path
exerce o caminho absoluto para o subdiretório. Caso você precise apenas do nome da pasta, você pode usá-lo entry.name
. Consulte os.DirEntry para obter detalhes adicionais sobre o entry
objeto.
use uma função de filtro os.path.isdir
sobre os.listdir()
algo como istofilter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])
Isso listará todos os subdiretórios na árvore de arquivos.
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
é novo na versão 3.4
Função para retornar uma Lista de todos os subdiretórios dentro de um determinado caminho do arquivo. Irá pesquisar em toda a árvore de arquivos.
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 obter uma lista de todas as pastas usando os.walk ()
import os
path = os.getcwd()
pathObject = os.walk(path)
esse pathObject é um objeto e podemos obter uma matriz
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 obter a lista de todos os subdiretórios iterando através da arr e imprimindo a matriz intermediária
for i in arr:
for j in i[1]:
print(j)
Isso imprimirá todo o subdiretório.
Para obter todos os arquivos:
for i in arr:
for j in i[2]:
print(i[0] + "/" + j)
Essa função, com um determinado pai, directory
repete toda a sua directories
recursividade e prints
tudo o filenames
que encontra por dentro. Muito ú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 ;")