Como listar apenas diretórios de nível superior em Python?


132

Quero poder listar apenas os diretórios dentro de alguma pasta. Isso significa que eu não quero nomes de arquivos listados, nem subpastas adicionais.

Vamos ver se um exemplo ajuda. No diretório atual, temos:

>>> 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']

No entanto, não quero nomes de arquivos listados. Também não quero subpastas como \ Lib \ curses. Essencialmente, o que eu quero funciona com o seguinte:

>>> for root, dirnames, filenames in os.walk('.'):
...     print dirnames
...     break
...
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'Scripts', 'tcl', 'Tools']

No entanto, estou me perguntando se existe uma maneira mais simples de obter os mesmos resultados. Tenho a impressão de que usar o os.walk apenas para retornar o nível superior é ineficiente / demais.

Respostas:


125

Filtre o resultado usando os.path.isdir () (e use os.path.join () para obter o caminho real):

>>> [ 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']

17
Isso exige muito processamento versus muito simples os.walk (). Next () [1]
Phyo Arkar Lwin

202

os.walk

Use os.walkcom a nextfunção item:

next(os.walk('.'))[1]

Para Python <= 2.5, use:

os.walk('.').next()[1]

Como isso funciona

os.walké um gerador e a chamada nextobterá o primeiro resultado na forma de três tuplas (caminho de rota, nome de diretório, nome de arquivo). Assim, o [1]índice retorna apenas o dirnamesdessa tupla.


14
Um pouco mais de descrição sobre isso é que este é um gerador, ele não estará caminhando nos outros diretórios, a menos que você diga. Então .next () [1] faz em uma linha o que todas as compreensões da lista fazem. Eu provavelmente faria algo assim DIRNAMES=1e, em seguida, next()[DIRNAMES]para facilitar o entendimento para futuros mantenedores de código.
boatcoder

3
+1 solução incrível. Para especificar um diretório para navegar, use:os.walk( os.path.join(mypath,'.')).next()[1]
Daniel Reis

42
para python v3: next (os.walk ('.')) [1]
Andre Soares

se você vai fazer mais do que processamento de texto; ou seja, o processamento nas pastas reais então caminhos completos podem ser necessários:sorted( [os.path.join(os.getcwd(), item) for item in os.walk(os.curdir).next()[1]] )
DevPlayer

52

Filtre a lista usando os.path.isdir para detectar diretórios.

filter(os.path.isdir, os.listdir(os.getcwd()))

5
Penso que esta é de longe a melhor combinação de legibilidade e concisão em qualquer uma dessas respostas.
vergenzt

20
Isso não funcionou. Meu palpite é que os.listdirretorna um nome de arquivo / pasta, passado para os.path.isdir, mas o último precisa de um caminho completo.
Daniel Reis

3
filtro é mais rápido do que os.walk timeit(os.walk(os.getcwd()).next()[1]) 1000 loops, best of 3: 734 µs per loop timeit(filter(os.path.isdir, os.listdir(os.getcwd()))) 1000 loops, best of 3: 477 µs per loop
B.Kocis

14
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]

4
Isto pode ser encurtado para filtro (os.path.isdir, os.listdir (os.getcwd ())
John Millikin

3
Alguém tem alguma informação sobre se a compreensão do filtro ou da lista é mais rápida? Caso contrário, é apenas um argumento subjetivo. Obviamente, isso pressupõe que há 10 milhões de diretórios no cwd e o desempenho é um problema.
Mark Roddy

12

Observe que, em vez de fazer os.listdir(os.getcwd()), é preferível fazer os.listdir(os.path.curdir). Menos uma chamada de função e é tão portátil.

Portanto, para concluir a resposta, obtenha uma lista de diretórios em uma pasta:

def listdirs(folder):
    return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]

Se você preferir nomes de caminho completos, use esta função:

def listdirs(folder):
    return [
        d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
        if os.path.isdir(d)
    ]

9

Isso parece funcionar também (pelo menos no linux):

import glob, os
glob.glob('*' + os.path.sep)

1
+1 para glob. Ele pode te salvar um monte de código, especialmente iterações, e é muito semelhante ao uso UNIX terminal ( ls)
Gerard

5
Em vez de glob.glob ('*' + os.path.sep), você pode escrever [dir para dir em glob.glob ("*") se os.path.isdir (dir)]
Eamonn MR

8

Apenas para acrescentar que o uso de os.listdir () não "exige muito processamento versus muito simples os.walk (). Next () [1]" . Isso ocorre porque o os.walk () usa os.listdir () internamente. De fato, se você testá-los juntos:

>>>> 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

A filtragem de os.listdir () é muito ligeiramente mais rápida.


2
Chegando em Python 3.5 é uma maneira mais rápida de obter o conteúdo do diretório: python.org/dev/peps/pep-0471
foz

1
pep-0471 - o scandirpacote - está disponível para o Python 2.6, como um pacote instalável no PyPI. Oferece substituições os.walke os.listdirque são muito mais rápidas.
foz

6

Uma maneira muito mais simples e elegante é usar isso:

 import os
 dir_list = os.walk('.').next()[1]
 print dir_list

Execute esse script na mesma pasta para a qual você deseja nomes de pastas. Ele fornecerá exatamente o nome imediato das pastas (isso também sem o caminho completo das pastas).


6

Usando a compreensão da lista,

[a for a in os.listdir() if os.path.isdir(a)]

Eu acho que é a maneira mais simples


2

sendo um novato aqui, ainda não posso comentar diretamente, mas aqui está uma pequena correção que gostaria de adicionar à parte seguinte do resposta ΤΖΩΤΖΙΟΥ :

Se você preferir nomes de caminho completos, use esta função:

def listdirs(folder):  
  return [
    d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
    if os.path.isdir(d)
]

para quem ainda está em python <2.4 : a construção interna precisa ser uma lista em vez de uma tupla e, portanto, deve ser assim:

def listdirs(folder):  
  return [
    d for d in [os.path.join(folder, d1) for d1 in os.listdir(folder)]
    if os.path.isdir(d)
  ]

caso contrário, obtém-se um erro de sintaxe.


Eu sei que já faz um tempo, mas esse primeiro exemplo realmente me ajudou.
Inbar Rose

1
Você recebe um erro de sintaxe porque sua versão não suporta expressões de gerador. Eles foram introduzidos no Python 2.4, enquanto as compreensões de lista estão disponíveis desde o Python 2.0.
precisa saber é o seguinte

1
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]

1

Para uma lista de nomes de caminhos completos, prefiro esta versão às outras soluções aqui:

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))]

1
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]

0

Uma opção mais segura que não falha quando não há diretório.

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 []

0

Igual a?

>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]

0

O Python 3.4 introduziu o pathlibmó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('./')
[f for f in p.iterdir() if f.is_dir()]

-1
-- 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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.