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.

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

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.


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

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

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

9

Ini sepertinya berfungsi juga (setidaknya di linux):

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

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.


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


6

Menggunakan pemahaman daftar,

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

Saya pikir ini adalah cara paling sederhana


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.


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

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

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

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

0

Seperti begitu?

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

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

-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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.