มีวิธีการส่งคืนรายการของไดเรกทอรีย่อยทั้งหมดในไดเรกทอรีปัจจุบันใน Python หรือไม่?
ฉันรู้ว่าคุณสามารถทำได้ด้วยไฟล์ แต่ฉันต้องได้รับรายชื่อของไดเรกทอรีแทน
มีวิธีการส่งคืนรายการของไดเรกทอรีย่อยทั้งหมดในไดเรกทอรีปัจจุบันใน Python หรือไม่?
ฉันรู้ว่าคุณสามารถทำได้ด้วยไฟล์ แต่ฉันต้องได้รับรายชื่อของไดเรกทอรีแทน
คำตอบ:
คุณหมายถึงไดเรกทอรีย่อยทันทีหรือทุกไดเรกทอรีลงต้นไม้หรือไม่
คุณสามารถใช้os.walk
วิธีนี้:
os.walk(directory)
จะให้ผลเป็น tuple สำหรับแต่ละไดเรกทอรีย่อย รายการแรกใน 3-tuple เป็นชื่อไดเรกทอรีดังนั้น
[x[0] for x in os.walk(directory)]
ควรให้ไดเรกทอรีย่อยทั้งหมดของคุณซ้ำ ๆ
โปรดทราบว่ารายการที่สองใน tuple คือรายการของไดเรกทอรีลูกของรายการในตำแหน่งแรกดังนั้นคุณสามารถใช้สิ่งนี้แทน แต่ไม่น่าจะช่วยคุณได้มากนัก
อย่างไรก็ตามคุณสามารถใช้เพื่อให้ไดเรกทอรีลูกทันที:
next(os.walk('.'))[1]
หรือดูวิธีแก้ไขปัญหาอื่น ๆ ที่โพสต์แล้วโดยใช้os.listdir
และos.path.isdir
รวมถึงที่ " วิธีรับไดเรกทอรีย่อยทั้งหมดใน Python "
os.walk('.').next()[1]
หรือos.walk('.').__next__()[1]
โดยตรง แต่ให้ใช้ในตัวฟังก์ชั่นnext()
ที่สามารถใช้ได้ทั้งในหลาม 2 (ดู doc)และงูหลาม 3 (ดู doc) ตัวอย่างเช่นnext(os.walk('.'))[1]
.
os.walk('.').next()[1]
โดยตรงจึงไม่ดี
iteraror.__next__()
เป็นวิธีการภายในและiterator.next()
การใช้งานควรเปลี่ยนไปใช้ในตัวnext()
ตาม PEP-3114 ดูPEP-3114ซึ่งได้รับการอนุมัติในปี 2007
os.walk
และโซลูชันos.listdir
+ os.path.isdir
: ฉันเพิ่งทดสอบในไดเรกทอรีที่มี 10,000 ไดเรกทอรีย่อย (มีไฟล์นับล้านในลำดับชั้นด้านล่าง) และความแตกต่างด้านประสิทธิภาพนั้นเล็กน้อย os.walk
: "10 ลูป, ดีที่สุด 3: 44.6 msec ต่อลูป" และos.listdir
+ os.path.isdir
: "10 ลูป, ดีที่สุด 3: 45.1 msec ต่อลูป"
import os
d = '.'
[os.path.join(d, o) for o in os.listdir(d)
if os.path.isdir(os.path.join(d,o))]
os.path.join
บนo
เพื่อให้ได้เส้นทางแบบเต็มมิฉะนั้นisdir(0)
จะกลับเท็จ
os.path.join
สองครั้งแรกคุณสามารถเข้าร่วมแล้วกรองรายการโดยใช้os.path.isdir
: filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
คุณสามารถใช้ glob.glob
from glob import glob
glob("/path/to/directory/*/")
อย่าลืมต่อท้ายหลังจากที่/
*
/
/
เป็นตัวแยกโฟลเดอร์ให้ทำดังนี้:glob(os.path.join(path_to_directory, "*", ""))
recursive=True
ดีกว่าด้านบนเนื่องจากคุณไม่ต้องการ os.path.join () หลายอันและคุณจะได้รับพา ธ แบบเต็มโดยตรง (ถ้าคุณต้องการ) คุณสามารถทำได้ในPython 3.5ขึ้นไป
subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]
สิ่งนี้จะให้เส้นทางที่สมบูรณ์ไปยังไดเรกทอรีย่อย หากคุณต้องการชื่อของการใช้ไดเรกทอรีย่อยf.name
แทนf.path
https://docs.python.org/3/library/os.html#os.scandir
OT เล็กน้อย: ในกรณีที่คุณต้องการโฟลเดอร์ย่อยทั้งหมดซ้ำและ / หรือไฟล์ทั้งหมดซ้ำเรียกดูฟังก์ชั่นนี้ที่เร็วกว่าos.walk
& glob
และจะส่งกลับรายการโฟลเดอร์ย่อยทั้งหมดรวมถึงไฟล์ทั้งหมดในโฟลเดอร์ย่อย (ย่อย): https://stackoverflow.com/a/59803793/2441026
ในกรณีที่คุณต้องการเฉพาะโฟลเดอร์ย่อยทั้งหมดซ้ำ :
def fast_scandir(dirname):
subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()]
for dirname in list(subfolders):
subfolders.extend(fast_scandir(dirname))
return subfolders
ส่งคืนรายการของโฟลเดอร์ย่อยทั้งหมดที่มีเส้นทางแบบเต็ม สิ่งนี้จะเร็วกว่าos.walk
และเร็วกว่าglob
มาก
การวิเคราะห์ฟังก์ชั่นทั้งหมด
TL; DR:
- ถ้าคุณต้องการที่จะได้รับทั้งหมดทันทีos.scandir
ไดเรกทอรีย่อยสำหรับการใช้งานโฟลเดอร์
- หากคุณต้องการได้รับไดเรกทอรีย่อยทั้งหมดแม้แต่ที่ซ้อนกันให้ใช้os.walk
หรือ - เร็วขึ้นเล็กน้อย - fast_scandir
ฟังก์ชั่นด้านบน
- การใช้งานไม่เคยสำหรับไดเรกทอรีย่อยระดับบนสุดเท่านั้นที่จะสามารถหลายร้อยครั้งช้ากว่าos.walk
(!)os.scandir
os.walk
จะเป็นโฟลเดอร์ฐาน ดังนั้นคุณจะไม่ได้รับเฉพาะไดเรกทอรีย่อย คุณสามารถใช้fu.pop(0)
เพื่อลบมันผลลัพธ์ :
os.scandir took 1 ms. Found dirs: 439
os.walk took 463 ms. Found dirs: 441 -> it found the nested one + base folder.
glob.glob took 20 ms. Found dirs: 439
pathlib.iterdir took 18 ms. Found dirs: 439
os.listdir took 18 ms. Found dirs: 439
ทดสอบกับ W7x64, Python 3.8.1
# -*- coding: utf-8 -*-
# Python 3
import time
import os
from glob import glob
from pathlib import Path
directory = r"<insert_folder>"
RUNS = 1
def run_os_walk():
a = time.time_ns()
for i in range(RUNS):
fu = [x[0] for x in os.walk(directory)]
print(f"os.walk\t\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_glob():
a = time.time_ns()
for i in range(RUNS):
fu = glob(directory + "/*/")
print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_pathlib_iterdir():
a = time.time_ns()
for i in range(RUNS):
dirname = Path(directory)
fu = [f for f in dirname.iterdir() if f.is_dir()]
print(f"pathlib.iterdir\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_os_listdir():
a = time.time_ns()
for i in range(RUNS):
dirname = Path(directory)
fu = [os.path.join(directory, o) for o in os.listdir(directory) if os.path.isdir(os.path.join(directory, o))]
print(f"os.listdir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_os_scandir():
a = time.time_ns()
for i in range(RUNS):
fu = [f.path for f in os.scandir(directory) if f.is_dir()]
print(f"os.scandir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms.\tFound dirs: {len(fu)}")
if __name__ == '__main__':
run_os_scandir()
run_os_walk()
run_glob()
run_pathlib_iterdir()
run_os_listdir()
หากคุณต้องการโซลูชันแบบเรียกซ้ำที่จะค้นหาไดเรกทอรีย่อยทั้งหมดในไดเรกทอรีย่อยให้ใช้ walk ตามที่เสนอมาก่อน
หากคุณต้องการเพียงไดเรกทอรีย่อยของไดเรกทอรีปัจจุบันให้รวมos.listdir
กับos.path.isdir
ฉันชอบที่จะใช้ตัวกรอง ( https://docs.python.org/2/library/functions.html#filter ) แต่นี่เป็นเพียงเรื่องของรสนิยม
d='.'
filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d))
ดำเนินการนี้โดยใช้ python-os-walk ( http://www.pythonforbeginners.com/code-snippets-source-code/python-os-walk/ )
import os
print("root prints out directories only from what you specified")
print("dirs prints out sub-directories from root")
print("files prints out all files from root and directories")
print("*" * 20)
for root, dirs, files in os.walk("/var/log"):
print(root)
print(dirs)
print(files)
คุณสามารถรับรายการไดเรกทอรีย่อย (และไฟล์) ใน Python 2.7 ได้โดยใช้ os.listdir (พา ธ )
import os
os.listdir(path) # list of subdirectories and files
os.listdir
รายการเนื้อหาของไดเรกทอรีรวมถึงไฟล์
print("\nWe are listing out only the directories in current directory -")
directories_in_curdir = filter(os.path.isdir, os.listdir(os.curdir))
print(directories_in_curdir)
files = filter(os.path.isfile, os.listdir(os.curdir))
print("\nThe following are the list of all files in the current directory -")
print(files)
งูหลาม 3.4 แนะนำโมดูลเข้าไปในห้องสมุดมาตรฐานที่ให้บริการเชิงวัตถุวิธีการเส้นทางการจัดการระบบแฟ้ม:pathlib
from pathlib import Path
p = Path('./')
# List comprehension
[f for f in p.iterdir() if f.is_dir()]
# The trailing slash to glob indicated directories
# This will also include the current directory '.'
list(p.glob('**/'))
Pathlib ยังมีอยู่ใน Python 2.7 ผ่านโมดูล pathlib2 บน PyPi
for f in filter(Path.is_dir, p.iterdir()):
เนื่องจากฉันเจอปัญหานี้โดยใช้ Python 3.4 และ Windows UNC path นี่เป็นตัวแปรสำหรับสภาพแวดล้อมนี้:
from pathlib import WindowsPath
def SubDirPath (d):
return [f for f in d.iterdir() if f.is_dir()]
subdirs = SubDirPath(WindowsPath(r'\\file01.acme.local\home$'))
print(subdirs)
Pathlib ใหม่ใน Python 3.4 และทำให้การทำงานกับพา ธ ภายใต้ OS ต่าง ๆ ง่ายขึ้นมาก: https://docs.python.org/3.4/library/pathlib.html
แม้ว่าคำถามนี้จะตอบมานานแล้ว ฉันต้องการแนะนำให้ใช้pathlib
โมดูลเนื่องจากนี่เป็นวิธีที่มีประสิทธิภาพในการทำงานบน Windows และ Unix OS
ดังนั้นเพื่อรับเส้นทางทั้งหมดในไดเรกทอรีเฉพาะรวมถึงไดเรกทอรีย่อย:
from pathlib import Path
paths = list(Path('myhomefolder', 'folder').glob('**/*.txt'))
# all sorts of operations
file = paths[0]
file.name
file.stem
file.parent
file.suffix
เป็นต้น
ขอบคุณสำหรับเคล็ดลับพวก ฉันพบปัญหาเกี่ยวกับซอฟต์ลิงค์ Softlinks? เราไม่ต้องการลิงก์ที่อ่อนนุ่มสำหรับ stinkin! ดังนั้น...
สิ่งนี้แสดงผลเฉพาะ dirs ไม่ใช่ softlink:
>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
[x[0] for x in inf]
เรียกว่าไพ ธ อนดังนั้นฉันจึงสามารถค้นหามันได้?
คัดลอกวางได้ง่ายในipython
:
import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))
ผลลัพธ์จากprint(folders)
:
['folderA', 'folderB']
x
เป็นรายการจากรายการที่สร้างโดยos.listdir(d)
เพราะlistdir
จะส่งคืนไฟล์และโฟลเดอร์ที่เขาใช้filter
คำสั่งด้วยos.path.isdir
เพื่อกรองไฟล์ใด ๆ ออกจากรายการ
นี่คือวิธีที่ฉันทำ
import os
for x in os.listdir(os.getcwd()):
if os.path.isdir(x):
print(x)
นี่คือฟังก์ชั่นพื้นฐานสองอย่างที่อ้างอิงจากตัวอย่างของ @Blair Conrad -
import os
def get_subdirs(dir):
"Get a list of immediate subdirectories"
return next(os.walk(dir))[1]
def get_subfiles(dir):
"Get a list of immediate subfiles"
return next(os.walk(dir))[2]
สร้างตามโซลูชันของ Eli Bendersky ใช้ตัวอย่างต่อไปนี้:
import os
test_directory = <your_directory>
for child in os.listdir(test_directory):
test_path = os.path.join(test_directory, child)
if os.path.isdir(test_path):
print test_path
# Do stuff to the directory "test_path"
โดยที่<your_directory>
เป็นพา ธ ไปยังไดเร็กทอรีที่คุณต้องการสำรวจ
ด้วยเส้นทางที่เต็มรูปแบบและการบัญชีสำหรับเส้นทางที่เป็นอยู่.
, ..
, \\
, ..\\..\\subfolder
ฯลฯ :
import os, pprint
pprint.pprint([os.path.join(os.path.abspath(path), x[0]) \
for x in os.walk(os.path.abspath(path))])
ดูเหมือนว่าคำตอบนี้จะไม่มีอยู่แล้ว
directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]
ผมเคยมีคำถามที่คล้ายกันเร็ว ๆ นี้และผมพบว่าคำตอบที่ดีที่สุดสำหรับการหลาม 3.6 (เป็น havlock ผู้ใช้ที่เพิ่มขึ้น) os.scandir
คือการใช้งาน เนื่องจากดูเหมือนว่าไม่มีวิธีใช้ฉันจะเพิ่มของฉันเอง ก่อนอื่นโซลูชันที่ไม่เรียกซ้ำที่แสดงรายการไดเรกทอรีย่อยโดยตรงภายใต้ไดเรกทอรีราก
def get_dirlist(rootdir):
dirlist = []
with os.scandir(rootdir) as rit:
for entry in rit:
if not entry.name.startswith('.') and entry.is_dir():
dirlist.append(entry.path)
dirlist.sort() # Optional, in case you want sorted directory names
return dirlist
เวอร์ชันเรียกซ้ำจะมีลักษณะเช่นนี้:
def get_dirlist(rootdir):
dirlist = []
with os.scandir(rootdir) as rit:
for entry in rit:
if not entry.name.startswith('.') and entry.is_dir():
dirlist.append(entry.path)
dirlist += get_dirlist(entry.path)
dirlist.sort() # Optional, in case you want sorted directory names
return dirlist
โปรดทราบว่าentry.path
wields พา ธ สัมบูรณ์ไปยังไดเร็กทอรีย่อย ในกรณีที่คุณต้องการชื่อโฟลเดอร์คุณสามารถใช้entry.name
แทน อ้างถึงos.DirEntryสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับentry
วัตถุ
ใช้ฟังก์ชันตัวกรองos.path.isdir
เหนือos.listdir()
บางสิ่งเช่นนี้filter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])
นี่จะแสดงรายการไดเรกทอรีย่อยทั้งหมดลงในแผนผังไฟล์
import pathlib
def list_dir(dir):
path = pathlib.Path(dir)
dir = []
try:
for item in path.iterdir():
if item.is_dir():
dir.append(item)
dir = dir + list_dir(item)
return dir
except FileNotFoundError:
print('Invalid directory')
pathlib
ใหม่ในเวอร์ชัน 3.4
ฟังก์ชั่นเพื่อกลับรายการของไดเรกทอรีย่อยทั้งหมดภายในเส้นทางไฟล์ที่กำหนด จะค้นหาทรีไฟล์ทั้งหมด
import os
def get_sub_directory_paths(start_directory, sub_directories):
"""
This method iterates through all subdirectory paths of a given
directory to collect all directory paths.
:param start_directory: The starting directory path.
:param sub_directories: A List that all subdirectory paths will be
stored to.
:return: A List of all sub-directory paths.
"""
for item in os.listdir(start_directory):
full_path = os.path.join(start_directory, item)
if os.path.isdir(full_path):
sub_directories.append(full_path)
# Recursive call to search through all subdirectories.
get_sub_directory_paths(full_path, sub_directories)
return sub_directories
เราสามารถรับรายชื่อของโฟลเดอร์ทั้งหมดโดยใช้ os.walk ()
import os
path = os.getcwd()
pathObject = os.walk(path)
นี้ pathObjectเป็นวัตถุและเราจะได้รับอาร์เรย์โดย
arr = [x for x in pathObject]
arr is of type [('current directory', [array of folder in current directory], [files in current directory]),('subdirectory', [array of folder in subdirectory], [files in subdirectory]) ....]
เราสามารถรับรายชื่อของไดเรกทอรีย่อยทั้งหมดโดยทำซ้ำผ่าน arrและพิมพ์อาร์เรย์กลาง
for i in arr:
for j in i[1]:
print(j)
สิ่งนี้จะพิมพ์ไดเรกทอรีย่อยทั้งหมด
ในการรับไฟล์ทั้งหมด:
for i in arr:
for j in i[2]:
print(i[0] + "/" + j)
ฟังก์ชั่นนี้กับผู้ปกครองที่กำหนดdirectory
iterates ทุกdirectories
ซ้ำและprints
ทั้งหมดfilenames
ที่มันพบภายใน มีประโยชน์มากเกินไป
import os
def printDirectoryFiles(directory):
for filename in os.listdir(directory):
full_path=os.path.join(directory, filename)
if not os.path.isdir(full_path):
print( full_path + "\n")
def checkFolders(directory):
dir_list = next(os.walk(directory))[1]
#print(dir_list)
for dir in dir_list:
print(dir)
checkFolders(directory +"/"+ dir)
printDirectoryFiles(directory)
main_dir="C:/Users/S0082448/Desktop/carpeta1"
checkFolders(main_dir)
input("Press enter to exit ;")
ด้วยการเข้าร่วมโซลูชั่นที่หลากหลายจากที่นี่นี่คือสิ่งที่ฉันลงเอยด้วยการใช้:
import os
import glob
def list_dirs(path):
return [os.path.basename(x) for x in filter(
os.path.isdir, glob.glob(os.path.join(path, '*')))]