Como obter todos os subdiretórios imediatos em Python
Pergunta
Eu estou tentando escrever um simples script Python que irá copiar um index.tpl para index.html em todos os subdiretórios (com algumas exceções).
Estou ficando atolados por tentar obter a lista de subdiretórios.
Solução
import os
def get_immediate_subdirectories(a_dir):
return [name for name in os.listdir(a_dir)
if os.path.isdir(os.path.join(a_dir, name))]
Outras dicas
Por que ninguém mencionou glob
? glob
permite usar expansão de nome Unix-style, e é minha a função para quase tudo o que precisa de encontrar mais do que um nome de caminho. Torna-se muito fácil:
from glob import glob
paths = glob('*/')
Note que glob
irá retornar o diretório com a barra final (como unix faria), enquanto a maioria das soluções baseadas path
vai omitir a barra final.
Verifique " Obtendo uma lista de todos os subdiretórios no diretório atual ".
Aqui está uma versão Python 3:
import os
dir_list = next(os.walk('.'))[1]
print(dir_list)
import os, os.path
Para obter (full-path) sub-diretórios imediatos em um diretório:
def SubDirPath (d):
return filter(os.path.isdir, [os.path.join(d,f) for f in os.listdir(d)])
Para obter a última (mais recente) sub-diretório:
def LatestDirectory (d):
return max(SubDirPath(d), key=os.path.getmtime)
os.walk
é seu amigo no esta situação.
Direto da documentação:
caminhada () gera os nomes de arquivos em uma árvore de diretórios, caminhando a árvore seja de cima para baixo ou para cima inferior. Para cada diretório na árvore com raiz no topo diretório (incluindo o próprio topo), que produz um 3-tupla (dirPath, dirnames, nomes de arquivos).
Este método bem faz tudo de uma vez.
from glob import glob
subd = [s.rstrip("/") for s in glob(parent_dir+"*/")]
Usando o módulo FilePath do Twisted:
from twisted.python.filepath import FilePath
def subdirs(pathObj):
for subpath in pathObj.walk():
if subpath.isdir():
yield subpath
if __name__ == '__main__':
for subdir in subdirs(FilePath(".")):
print "Subdirectory:", subdir
Uma vez que alguns comentaristas pediram que as vantagens da utilização de bibliotecas de torcida para isso é, eu vou um pouco além da pergunta original aqui.
Há alguma documentação melhorada em um ramo que explica as vantagens de FilePath; você pode querer ler isso.
Mais especificamente neste exemplo: ao contrário da versão da biblioteca padrão, esta função pode ser implementado com não importações . A função "subdirs" é totalmente genérico, em que ela opera em nada, mas seu argumento. A fim de copiar e mover os arquivos usando a biblioteca padrão, você precisa depender do builtin "open
", "listdir
", talvez "isdir
" ou "os.walk
" ou "shutil.copy
". Talvez "os.path.join
" também. Sem mencionar o fato de que você precisa de uma seqüência passada um argumento para identificar o arquivo real. Vamos dar uma olhada na implementação integral que irá copiar "index.tpl" de cada diretório para "index.html":
def copyTemplates(topdir):
for subdir in subdirs(topdir):
tpl = subdir.child("index.tpl")
if tpl.exists():
tpl.copyTo(subdir.child("index.html"))
A função "subdirs" acima pode funcionar em qualquer FilePath
-como objeto. O que significa, entre outras coisas, ZipPath
objetos. Infelizmente ZipPath
é só de leitura no momento, mas pode ser estendido para a escrita de apoio.
Você também pode passar seus próprios objetos para fins de teste. A fim de testar as APIs-usando os.path sugeridas aqui, você tem que macaco com nomes importados e dependências implícitas e geralmente realizar a magia negra para obter seus testes para o trabalho. Com FilePath, você fazer algo como isto:
class MyFakePath:
def child(self, name):
"Return an appropriate child object"
def walk(self):
"Return an iterable of MyFakePath objects"
def exists(self):
"Return true or false, as appropriate to the test"
def isdir(self):
"Return true or false, as appropriate to the test"
...
subdirs(MyFakePath(...))
Eu escrevi algum código para mover máquinas virtuais VMware em torno, e acabou usando os.path
e shutil
para realizar cópia de arquivos entre sub-diretórios.
def copy_client_files (file_src, file_dst):
for file in os.listdir(file_src):
print "Copying file: %s" % file
shutil.copy(os.path.join(file_src, file), os.path.join(file_dst, file))
Não é terrivelmente elegante, mas ela não funciona.
Aqui está uma maneira:
import os
import shutil
def copy_over(path, from_name, to_name):
for path, dirname, fnames in os.walk(path):
for fname in fnames:
if fname == from_name:
shutil.copy(os.path.join(path, from_name), os.path.join(path, to_name))
copy_over('.', 'index.tpl', 'index.html')
def get_folders_in_directories_recursively(self, directory, index=0):
folder_list = list()
parent_directory = directory
for path, subdirs, _ in os.walk(directory):
if not index:
for sdirs in subdirs:
folder_path = "{}/{}".format(path, sdirs)
folder_list.append(folder_path)
elif path[len(parent_directory):].count('/') + 1 == index:
for sdirs in subdirs:
folder_path = "{}/{}".format(path, sdirs)
folder_list.append(folder_path)
return folder_list
A função a seguir pode ser chamado como:
get_folders_in_directories_recursively (diretório, index = 1) -> fornece a lista de pastas no primeiro nível
get_folders_in_directories_recursively (diretório) -> dá todas as sub-pastas
Eu tenho que mencionar a path.py biblioteca, que eu uso muito frequentemente.
Buscando os subdiretórios imediatos se tornar tão simples como isso:
my_dir.dirs()
O exemplo de trabalho completo é:
from path import Path
my_directory = Path("path/to/my/directory")
subdirs = my_directory.dirs()
NB: my_directory ainda podem ser manipulados como uma cadeia de caracteres, uma vez que o caminho é uma subclasse de corda, mas proporcionando um grupo de métodos úteis para a manipulação de percursos
import glob
import os
def child_dirs(path):
cd = os.getcwd() # save the current working directory
os.chdir(path) # change directory
dirs = glob.glob("*/") # get all the subdirectories
os.chdir(cd) # change directory to the script original location
return dirs
A função child_dirs
toma um caminho um diretório e retorna uma lista de subdiretórios imediatos na mesma.
dir
|
-- dir_1
-- dir_2
child_dirs('dir') -> ['dir_1', 'dir_2']
import pathlib
def list_dir(dir):
path = pathlib.Path(dir)
dir = []
try:
for item in path.iterdir():
if item.is_dir():
dir.append(item)
return dir
except FileNotFoundError:
print('Invalid directory')