Bagaimana cara mendaftar hanya direktori tingkat atas di Python?

132

Saya ingin hanya dapat mendaftar direktori di dalam beberapa folder. Ini berarti saya tidak ingin nama file terdaftar, saya juga tidak ingin sub-folder tambahan.

Mari kita lihat apakah sebuah contoh membantu. Dalam direktori saat ini kami memiliki:

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

Namun, saya tidak ingin nama file terdaftar. Saya juga tidak ingin sub-folder seperti \ Lib \ curses. Pada dasarnya apa yang saya inginkan berfungsi dengan yang berikut:

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

Namun, saya bertanya-tanya apakah ada cara yang lebih sederhana untuk mencapai hasil yang sama. Saya mendapat kesan bahwa menggunakan os.walk hanya untuk mengembalikan level atas tidak efisien / terlalu banyak.

fuentesjr
sumber

Jawaban:

125

Memfilter hasil menggunakan os.path.isdir () (dan menggunakan os.path.join () untuk mendapatkan jalur nyata):

>>> [ 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']
Thomas Wouters
sumber
17
Ini membutuhkan banyak pemrosesan vs os.walk yang sangat sederhana (). Next () [1]
Phyo Arkar Lwin
204

os.walk

Gunakan os.walkdengan nextfungsi item:

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

Untuk Python <= 2,5 gunakan:

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

Bagaimana ini bekerja?

os.walkadalah generator dan panggilan nextakan mendapatkan hasil pertama dalam bentuk 3-tuple (dirpath, dirnames, nama file). Dengan demikian [1]indeks hanya mengembalikan dirnamesdari tuple itu.

Alex Coventry
sumber
14
Sedikit penjelasan lebih lanjut tentang ini adalah bahwa ini adalah generator, itu tidak akan berjalan dir lain kecuali Anda menyuruhnya. Jadi .next () [1] melakukan dalam satu baris apa yang dilakukan semua pemahaman daftar. Saya mungkin akan melakukan sesuatu seperti DIRNAMES=1dan kemudian next()[DIRNAMES]membuatnya lebih mudah untuk dipahami oleh pengelola kode di masa depan.
boatcoder
3
+1 solusi luar biasa. Untuk menentukan direktori yang akan ditelusuri, gunakan:os.walk( os.path.join(mypath,'.')).next()[1]
Daniel Reis
42
untuk python v3: next (os.walk ('.')) [1]
Andre Soares
jika Anda akan melakukan lebih dari pemrosesan teks; yaitu memproses dalam folder aktual maka jalur penuh mungkin diperlukan:sorted( [os.path.join(os.getcwd(), item) for item in os.walk(os.curdir).next()[1]] )
DevPlayer
52

Saring daftar menggunakan os.path.isdir untuk mendeteksi direktori.

filter(os.path.isdir, os.listdir(os.getcwd()))
Colin Jensen
sumber
5
Saya pikir ini adalah kombinasi terbaik dari keterbacaan dan keringkasan dalam jawaban-jawaban ini.
vergenzt
20
Ini tidak berhasil. Dugaan saya adalah bahwa os.listdirmengembalikan nama file / folder, diteruskan ke os.path.isdir, tetapi yang terakhir membutuhkan path lengkap.
Daniel Reis
3
filter lebih cepat daripada 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
os.walk
14
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
Mark Roddy
sumber
4
Ini dapat disingkat menjadi filter (os.path.isdir, os.listdir (os.getcwd ())
John Millikin
3
Apakah ada yang punya informasi tentang apakah filter atau pemahaman daftar lebih cepat? Kalau tidak, itu hanya argumen subyektif. Ini tentu saja mengasumsikan ada 10 juta direktori di cwd dan kinerja adalah masalah.
Mark Roddy
12

Perhatikan bahwa, alih-alih melakukan os.listdir(os.getcwd()), itu lebih baik dilakukanos.listdir(os.path.curdir) . Satu panggilan fungsi kurang, dan itu sebagai portabel.

Jadi, untuk melengkapi jawabannya, untuk mendapatkan daftar direktori di folder:

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

Jika Anda lebih suka nama path lengkap, gunakan fungsi ini:

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

Ini sepertinya berfungsi juga (setidaknya di linux):

import glob, os
glob.glob('*' + os.path.sep)
Travis
sumber
1
+1 untuk glob. Ini dapat menghemat banyak kode, terutama iterasi, dan sangat mirip dengan penggunaan terminal UNIX ( ls)
Gerard
5
Daripada glob.glob ('*' + os.path.sep) Anda mungkin ingin menulis [dir untuk dir di glob.glob ("*") jika os.path.isdir (dir)]
Eamonn MR
8

Hanya untuk menambahkan bahwa menggunakan os.listdir () tidak "mengambil banyak pemrosesan vs os.walk sangat sederhana (). Next () [1]" . Ini karena os.walk () menggunakan os.listdir () secara internal. Bahkan jika Anda mengujinya bersama:

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

Pemfilteran os.listdir () sangat sedikit lebih cepat.

teman
sumber
2
Datang dengan Python 3.5 adalah cara yang lebih cepat untuk mendapatkan konten direktori: python.org/dev/peps/pep-0471
foz
1
pep-0471 - scandirpaket - tersedia untuk Python 2.6 dan seterusnya sebagai paket yang dapat diinstal di PyPI. Menawarkan penggantian untuk os.walkdan os.listdiryang jauh lebih cepat.
foz
6

Cara yang sangat sederhana dan elegan adalah dengan menggunakan ini:

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

Jalankan skrip ini di folder yang sama yang Anda inginkan nama folder. Ini akan memberi Anda persis nama folder langsung saja (itu juga tanpa path lengkap folder).

manty
sumber
6

Menggunakan pemahaman daftar,

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

Saya pikir ini adalah cara paling sederhana

KBLee
sumber
2

menjadi pemula di sini saya belum bisa berkomentar secara langsung tetapi di sini ada koreksi kecil saya ingin menambahkan ke bagian berikut dari jawaban ΤΖΩΤΖΙΟΥ :

Jika Anda lebih suka nama path lengkap, gunakan fungsi ini:

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

bagi yang masih menggunakan python <2.4 : konstruk dalam perlu daftar bukan tupel dan karena itu harus membaca seperti ini:

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

jika tidak, orang akan mendapatkan kesalahan sintaksis.

antiplex
sumber
Saya tahu ini sudah lama, tapi contoh pertama ini sangat membantu saya.
Inbar Rose
1
Anda mendapatkan kesalahan sintaksis karena versi Anda tidak mendukung ekspresi generator. Ini diperkenalkan di Python 2.4 sedangkan daftar pemahaman telah tersedia sejak Python 2.0.
awatts
1
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]
Moe
sumber
1

Untuk daftar nama jalur lengkap, saya lebih suka versi ini daripada solusi lain di sini:

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))]
Malius Arth
sumber
1
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]
nvd
sumber
0

Opsi yang lebih aman yang tidak gagal saat tidak ada direktori.

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 []
Alexey Gavrilov
sumber
0

Seperti begitu?

>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]
Kirk Strauser
sumber
0

Python 3.4 diperkenalkan pada pathlibmodul ke dalam perpustakaan standar, yang menyediakan pendekatan berorientasi objek untuk jalur menangani filesystem:

from pathlib import Path

p = Path('./')
[f for f in p.iterdir() if f.is_dir()]
joelostblom
sumber
-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
venkata maddineni
sumber