จะแสดงเฉพาะไดเรกทอรีระดับบนสุดใน Python ได้อย่างไร?


132

ฉันต้องการแสดงเฉพาะไดเร็กทอรีภายในบางโฟลเดอร์ ซึ่งหมายความว่าฉันไม่ต้องการให้แสดงชื่อไฟล์และไม่ต้องการโฟลเดอร์ย่อยเพิ่มเติม

ลองดูว่าตัวอย่างช่วยได้ไหม ในไดเร็กทอรีปัจจุบันเรามี:

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

อย่างไรก็ตามฉันไม่ต้องการให้แสดงชื่อไฟล์ ฉันไม่ต้องการโฟลเดอร์ย่อยเช่น \ Lib \ curses โดยพื้นฐานแล้วสิ่งที่ฉันต้องการทำงานได้ดังต่อไปนี้:

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

อย่างไรก็ตามฉันสงสัยว่ามีวิธีที่ง่ายกว่านี้ในการบรรลุผลลัพธ์เดียวกันหรือไม่ ฉันรู้สึกว่าการใช้ os.walk เพียงเพื่อคืนระดับบนสุดนั้นไม่มีประสิทธิภาพ / มากเกินไป

คำตอบ:


126

กรองผลลัพธ์โดยใช้ os.path.isdir () (และใช้ os.path.join () เพื่อรับเส้นทางจริง):

>>> [ 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
การประมวลผลนี้ใช้เวลามากเทียบกับ os.walk () ที่เรียบง่ายมาก next () [1]
Phyo Arkar Lwin

204

os.walk

ใช้os.walkกับnextฟังก์ชันรายการ:

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

สำหรับPython <= 2.5 ให้ใช้:

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

วิธีการทำงาน

os.walkเป็นเครื่องกำเนิดไฟฟ้าและการโทรnextจะได้ผลลัพธ์แรกในรูปแบบของ 3-tuple (dirpath, dirnames, filenames) ดังนั้น[1]ดัชนีจะส่งคืนเฉพาะdirnamesจากทูเปิลนั้น


14
คำอธิบายเพิ่มเติมเล็กน้อยเกี่ยวกับสิ่งนี้คือนี่คือเครื่องกำเนิดไฟฟ้ามันจะไม่เดินไปที่เขื่อนอื่น ๆ เว้นแต่คุณจะบอกให้ ดังนั้น .next () [1] ในบรรทัดเดียวคือสิ่งที่ความเข้าใจในรายการทั้งหมดทำ ฉันอาจจะทำอะไรบางอย่างDIRNAMES=1แล้วnext()[DIRNAMES]เพื่อให้เข้าใจง่ายขึ้นสำหรับผู้ดูแลรหัสในอนาคต
boatcoder

3
+1 ทางออกที่น่าทึ่ง ในการระบุไดเร็กทอรีเพื่อเรียกดูให้ใช้:os.walk( os.path.join(mypath,'.')).next()[1]
Daniel Reis

42
สำหรับ python v3: next (os.walk ('.')) [1]
Andre Soares

ถ้าคุณจะทำมากกว่านั้นการประมวลผลข้อความ เช่นการประมวลผลในโฟลเดอร์จริงอาจจำเป็นต้องใช้เส้นทางแบบเต็ม:sorted( [os.path.join(os.getcwd(), item) for item in os.walk(os.curdir).next()[1]] )
DevPlayer

52

กรองรายการโดยใช้ os.path.isdir เพื่อตรวจหาไดเร็กทอรี

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

5
ฉันคิดว่านี่เป็นการผสมผสานที่ดีที่สุดของความสามารถในการอ่านและความกระชับในคำตอบเหล่านี้
vergenzt

20
สิ่งนี้ไม่ได้ผล ฉันเดาว่าos.listdirส่งคืนชื่อไฟล์ / โฟลเดอร์ส่งต่อไปos.path.isdirแต่ส่วนหลังต้องการพา ธ แบบเต็ม
Daniel Reis

3
ตัวกรองเร็วกว่า 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
สามารถย่อให้สั้นลงเพื่อกรอง (os.path.isdir, os.listdir (os.getcwd ())
John Millikin

3
ใครมีข้อมูลว่าตัวกรองหรือความเข้าใจรายการเร็วกว่านี้ไหม มิฉะนั้นจะเป็นเพียงการโต้แย้งส่วนตัว แน่นอนว่านี่ถือว่ามีไดเรกทอรี 10 ล้านไดเรกทอรีใน cwd และประสิทธิภาพเป็นปัญหา
Mark Roddy

12

โปรดทราบว่าแทนที่จะทำos.listdir(os.getcwd())ควรทำos.listdir(os.path.curdir)มากกว่า การเรียกใช้ฟังก์ชันน้อยกว่าหนึ่งครั้งและเป็นแบบพกพา

ดังนั้นเพื่อให้คำตอบสมบูรณ์เพื่อรับรายการไดเรกทอรีในโฟลเดอร์:

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

หากคุณต้องการชื่อพา ธ แบบเต็มให้ใช้ฟังก์ชันนี้:

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

ดูเหมือนว่าจะได้ผลเช่นกัน (อย่างน้อยใน linux):

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

1
+1 สำหรับglob. ช่วยให้คุณประหยัดรหัสได้มากโดยเฉพาะการทำซ้ำและคล้ายกับการใช้งานเทอร์มินัล UNIX ( ls)
เจอราร์ด

5
แทนที่จะเป็น glob.glob ('*' + os.path.sep) คุณอาจต้องการเขียน [dir for dir ใน glob.glob ("*") ถ้า os.path.isdir (dir)]
Eamonn MR

8

เพียงเพื่อเพิ่มว่าการใช้ os.listdir () ไม่ได้"ใช้เวลามากของการประมวลผลเทียบ os.walk ง่ายมาก (). ถัดไป () [1]" เนื่องจาก os.walk () ใช้ os.listdir () เป็นการภายใน ในความเป็นจริงถ้าคุณทดสอบด้วยกัน:

>>>> 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 () เร็วขึ้นเล็กน้อย


2
การมาใน Python 3.5 เป็นวิธีที่เร็วกว่าในการรับเนื้อหาไดเรกทอรี: python.org/dev/peps/pep-0471
สำหรับ

1
pep-0471 - scandirแพ็กเกจ - พร้อมใช้งานอย่างมีความสุขสำหรับ Python 2.6 เป็นต้นไปเป็นแพ็คเกจที่ติดตั้งได้บน PyPI มีการเปลี่ยนos.walkและos.listdirที่เร็วกว่ามาก
foz

6

วิธีที่ง่ายและสง่างามมากคือการใช้สิ่งนี้:

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

เรียกใช้สคริปต์นี้ในโฟลเดอร์เดียวกับที่คุณต้องการชื่อโฟลเดอร์มันจะให้ชื่อโฟลเดอร์ที่ถูกต้องเท่านั้น (ซึ่งก็ไม่มีเส้นทางแบบเต็มของโฟลเดอร์)


6

การใช้ความเข้าใจในรายการ

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

ฉันคิดว่ามันเป็นวิธีที่ง่ายที่สุด


2

เป็นมือใหม่ที่นี่ฉันยังไม่สามารถแสดงความคิดเห็นได้โดยตรง แต่นี่คือการแก้ไขเล็กน้อยที่ฉันต้องการเพิ่มในส่วนต่อไปนี้ของคำตอบของΤΖΩΤΖΙΟΥ :

หากคุณต้องการชื่อพา ธ แบบเต็มให้ใช้ฟังก์ชันนี้:

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

สำหรับผู้ที่ยังอยู่ใน python <2.4 : โครงสร้างด้านในจะต้องเป็นรายการแทนที่จะเป็นทูเปิลดังนั้นจึงควรอ่านดังนี้:

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

มิฉะนั้นจะมีข้อผิดพลาดทางไวยากรณ์


ฉันรู้ว่ามันผ่านมาระยะหนึ่งแล้ว แต่ตัวอย่างแรกนี้ช่วยฉันได้จริงๆ
Inbar Rose

1
คุณได้รับข้อผิดพลาดทางไวยากรณ์เนื่องจากเวอร์ชันของคุณไม่รองรับนิพจน์ตัวสร้าง สิ่งเหล่านี้ถูกนำมาใช้ใน Python 2.4 ในขณะที่ความเข้าใจรายการมีให้ตั้งแต่ Python 2.0
awatts


1

สำหรับรายการชื่อพา ธ แบบเต็มฉันชอบเวอร์ชันนี้มากกว่าโซลูชันอื่น ๆที่นี่:

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


0

ตัวเลือกที่ปลอดภัยกว่าที่ไม่ล้มเหลวเมื่อไม่มีไดเร็กทอรี

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

งูหลาม 3.4 แนะนำโมดูลเข้าไปในห้องสมุดมาตรฐานที่ให้บริการเชิงวัตถุวิธีการเส้นทางการจัดการระบบแฟ้ม:pathlib

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.