Python'da yalnızca en üst düzey dizinler nasıl listelenir?


132

Yalnızca bazı klasörlerin içindeki dizinleri listeleyebilmek istiyorum. Bu, dosya adlarının listelenmesini istemediğim veya ek alt klasörler istemediğim anlamına gelir.

Bakalım bir örnek yardımcı olacak mı? Mevcut dizinde biz var:

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

Ancak, dosya adlarının listelenmesini istemiyorum. \ Lib \ curses gibi alt klasörler de istemiyorum. Esasen istediğim şey aşağıdakilerle çalışıyor:

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

Bununla birlikte, aynı sonuçları elde etmenin daha basit bir yolu olup olmadığını merak ediyorum. Os.walk'u yalnızca en üst seviyeye dönmek için kullanmanın verimsiz / çok fazla olduğu izlenimini edindim.

Yanıtlar:


126

Sonucu os.path.isdir () kullanarak filtreleyin (ve gerçek yolu elde etmek için os.path.join () kullanın):

>>> [ 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
Bu, çok basit os.walk () 'a kıyasla çok fazla işlem gerektirir. Next () [1]
Phyo Arkar Lwin

204

os.walk

Öğe işlevi os.walkile kullanın next:

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

İçin Python <2.5 = kullanımını:

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

Bu nasıl çalışır

os.walkbir nextüreteçtir ve çağrı , ilk sonucu 3'lük bir demet (dirpath, dirnames, filenames) şeklinde alır. Dolayısıyla, [1]dizin yalnızca dirnamesbu diziden döndürür .


14
Bununla ilgili biraz daha açıklama, bunun bir jeneratör olduğudur, siz söylemedikçe diğer yönlerde yürümeyecektir. Yani .next () [1] tüm liste anlayışlarının yaptığını tek satırda yapıyor. Muhtemelen buna benzer bir şey yapardım DIRNAMES=1ve sonra next()[DIRNAMES]gelecekteki kod bakıcılarının anlaşılmasını kolaylaştırmak için.
boatcoder

3
+1 harika çözüm. Göz atılacak bir dizin belirtmek için şunu kullanın:os.walk( os.path.join(mypath,'.')).next()[1]
Daniel Reis

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

metin işlemeden daha fazlasını yapacaksanız; yani, gerçek klasörlerde işlenmesi, ardından tam yollar gerekebilir:sorted( [os.path.join(os.getcwd(), item) for item in os.walk(os.curdir).next()[1]] )
DevPlayer

52

Dizinleri algılamak için os.path.isdir kullanarak listeyi filtreleyin.

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

5
Bence bu, bu cevapların herhangi birinde okunabilirlik ve özlü olmanın açık ara en iyi kombinasyonu.
vergenzt

20
Bu işe yaramadı. Tahminim, os.listdirbir dosya / klasör adı döndürür, aktarılır os.path.isdir, ancak ikincisi tam bir yola ihtiyaç duyar.
Daniel Reis

3
filtresi os.walk'tan daha hızlı 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
Bu, filtrelemek için kısaltılabilir (os.path.isdir, os.listdir (os.getcwd ())
John Millikin

3
Filtreleme veya liste anlamanın daha hızlı olup olmadığı konusunda bilgisi olan var mı? Aksi takdirde, bu sadece öznel bir argümandır. Elbette bu, cwd'de 10 milyon dizin olduğunu ve performansın bir sorun olduğunu varsayar.
Mark Roddy

12

os.listdir(os.getcwd())Yapmak yerine yapmanın tercih edildiğini unutmayın.os.listdir(os.path.curdir) . Bir fonksiyon daha az ve taşınabilir.

Öyleyse, cevabı tamamlamak için, bir klasördeki dizinlerin bir listesini almak için:

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

Tam yol adlarını tercih ediyorsanız, bu işlevi kullanın:

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

Bu da çalışıyor gibi görünüyor (en azından Linux'ta):

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

1
+1 glob. Size çok sayıda kod, özellikle yinelemelerden tasarruf sağlayabilir ve UNIX terminal kullanımına çok benzer ( ls)
Gerard

5
Glob.glob ('*' + os.path.sep) yerine, os.path.isdir (dir)]
Eamonn MR

8

Sadece os.listdir () kullanmanın "çok basit os.walk (). Next () [1]" yerine çok fazla işlem gerektirmediğini eklemek gerekir . Bunun nedeni os.walk () 'un dahili olarak os.listdir () kullanmasıdır. Aslında onları birlikte test ederseniz:

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

Os.listdir () 'in süzülmesi çok az daha hızlıdır.


2
Python 3.5 ile gelmek, dizin içeriğini almanın daha hızlı bir yoludur: python.org/dev/peps/pep-0471
foz

1
pep-0471 - scandirpaket - PyPI üzerinde kurulabilir bir paket olarak Python 2.6'dan itibaren memnuniyetle mevcuttur. Değiştirmeler sunar os.walkve os.listdirbu çok daha hızlıdır.
foz

6

Bunu kullanmak çok daha basit ve zarif bir yol:

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

Bu komut dosyasını, klasör adlarını istediğiniz klasörde çalıştırın.Size yalnızca hemen klasör adını verecektir (klasörlerin tam yolu olmadan da).


6

Liste anlama özelliğini kullanarak,

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

Bence bu en basit yol


2

Burada yeni başlayan biri olarak henüz doğrudan yorum yapamam ama işte küçük bir düzeltme ΤΖΩΤΖΙΟΥ cevabının aşağıdaki bölümüne eklemek istiyorum :

Tam yol adlarını tercih ediyorsanız, bu işlevi kullanın:

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

hala python <2.4 kullananlar için : iç yapının bir demet yerine bir liste olması gerekir ve bu nedenle şöyle okumalıdır:

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

aksi takdirde sözdizimi hatası alırsınız.


Bir süredir biliyorum ama bu ilk örnek bana gerçekten yardımcı oldu.
Inbar Gül

1
Sürümünüz oluşturucu ifadelerini desteklemediği için bir sözdizimi hatası alıyorsunuz. Bunlar Python 2.4'te tanıtıldı, oysa liste anlamaları Python 2.0'dan beri mevcut.
awatts

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

1

Tam yol adlarının bir listesi için bu sürümü buradaki diğer çözümlere tercih ediyorum :

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

Dizin olmadığında başarısız olmayan daha güvenli bir seçenek.

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

Öyle mi?

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

0

Python 3.4 , pathlibmodülü dosya sistemi yollarını işlemek için nesne yönelimli bir yaklaşım sağlayan standart kitaplığa tanıttı :

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.