ฉันจะวนซ้ำไฟล์ในไดเรกทอรีที่กำหนดได้อย่างไร


555

ฉันต้องวนซ้ำ.asmไฟล์ทั้งหมดในไดเรกทอรีที่กำหนดและดำเนินการบางอย่างกับพวกเขา

วิธีนี้สามารถทำได้อย่างมีประสิทธิภาพ?

คำตอบ:


807

คำตอบเดิม:

import os

for filename in os.listdir(directory):
    if filename.endswith(".asm") or filename.endswith(".py"): 
         # print(os.path.join(directory, filename))
        continue
    else:
        continue

Python 3.6 รุ่นของคำตอบข้างต้นโดยใช้os- สมมติว่าคุณมีเส้นทางไดเรกทอรีเป็นstrวัตถุในตัวแปรที่เรียกว่าdirectory_in_str:

import os

directory = os.fsencode(directory_in_str)

for file in os.listdir(directory):
     filename = os.fsdecode(file)
     if filename.endswith(".asm") or filename.endswith(".py"): 
         # print(os.path.join(directory, filename))
         continue
     else:
         continue

หรือเรียกซ้ำโดยใช้pathlib:

from pathlib import Path

pathlist = Path(directory_in_str).glob('**/*.asm')
for path in pathlist:
     # because path is object not string
     path_in_str = str(path)
     # print(path_in_str)

1
ดูเหมือนว่าจะแสดงรายการไดเรกทอรีหรือไฟล์ทันทีภายใต้ไดเรกทอรี คำตอบโดย pedromateo ด้านล่างดูเหมือนว่าจะทำรายการซ้ำ
Jay Sheth

8
โปรดทราบว่าในไดเรกทอรี Python 3.6 คาดว่าจะอยู่ในหน่วยไบต์จากนั้น listdir จะแยกรายการชื่อไฟล์เป็นประเภทข้อมูลไบต์ดังนั้นคุณจึงไม่สามารถเรียกใช้ endswith ได้โดยตรง บล็อกรหัสนี้ควรเปลี่ยนเป็นdirectory = os.fsencode(directory_in_str) for file in os.listdir(directory): filename = os.fsdecode(file) if filename.endswith(".asm") or filename.endswith(".py"): # print(os.path.join(directory, filename)) continue else: continue
Kim Stacks

13
print(os.path.join(directory, filename))ต้องเปลี่ยนเป็นprint(os.path.join(directory_in_str, filename))เพื่อให้ทำงานใน python 3.6
Hugo Koopmans

54
หากคุณเห็นสิ่งนี้ในปี 2560 หรือสูงกว่าปัจจุบัน os.scandir (dir_str) พร้อมใช้งานแล้วและสะอาดกว่ามากเมื่อใช้งาน ไม่จำเป็นต้องใช้ fsencode for entry in os.scandir(path): print(entry.path)
goat

2
ต้องการif filename.endswith((".asm", ".py")):ที่จะif filename.endswith(".asm") or filename.endswith(".py"):
Maroloccio

152

สิ่งนี้จะวนซ้ำไฟล์ที่สืบทอดทั้งหมดไม่ใช่เฉพาะไฟล์ย่อยของไดเรกทอรี:

import os

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        #print os.path.join(subdir, file)
        filepath = subdir + os.sep + file

        if filepath.endswith(".asm"):
            print (filepath)

3
การอ้างอิงสำหรับฟังก์ชัน os.walk มีดังต่อไปนี้: docs.python.org/2/library/os.path.html#os.path.walk
ScottMcC

136

คุณสามารถลองใช้โมดูลglob :

import glob

for filepath in glob.iglob('my_dir/*.asm'):
    print(filepath)

และเนื่องจาก Python 3.5 คุณสามารถค้นหาไดเรกทอรีย่อยได้เช่นกัน:

glob.glob('**/*.txt', recursive=True) # => ['2.txt', 'sub/3.txt']

จากเอกสาร:

โมดูล glob พบชื่อพา ธ ทั้งหมดที่ตรงกับรูปแบบที่ระบุตามกฎที่ใช้โดยเชลล์ Unix แม้ว่าผลลัพธ์จะถูกส่งคืนตามลำดับโดยพลการ จะไม่มีการขยายตัวหนอน แต่ *,? และช่วงอักขระที่แสดงด้วย [] จะถูกจับคู่อย่างถูกต้อง


19

ตั้งแต่ Python 3.5 ทุกอย่างง่ายขึ้นด้วยos.scandir ( )

with os.scandir(path) as it:
    for entry in it:
        if entry.name.endswith(".asm") and entry.is_file():
            print(entry.name, entry.path)

การใช้ scandir () แทนที่จะเป็น listdir () สามารถเพิ่มประสิทธิภาพของโค้ดที่ต้องการข้อมูลประเภทไฟล์หรือข้อมูลแอตทริบิวต์ไฟล์ได้อย่างมีนัยสำคัญเนื่องจากอ็อบเจ็กต์ os.DirEntry จะเปิดเผยข้อมูลนี้หากระบบปฏิบัติการจัดเตรียมไว้เมื่อสแกนไดเรกทอรี เมธอด os.DirEntry ทั้งหมดอาจทำการเรียกระบบ แต่ is_dir () และ is_file () มักจะต้องการการเรียกใช้ระบบสำหรับลิงก์สัญลักษณ์เท่านั้น os.DirEntry.stat () ต้องมีการเรียกระบบบนยูนิกซ์เสมอ แต่ต้องการเพียงหนึ่งสำหรับลิงก์สัญลักษณ์บน Windows


entryเป็น posix.DirEntryประเภทกับพวงของวิธีการที่มีประโยชน์เช่นentry.is_dir(), is_file(),is_symlink()
crypdick

17

Python 3.4 และใหม่กว่าเสนอpathlibในไลบรารีมาตรฐาน คุณสามารถทำได้:

from pathlib import Path

asm_pths = [pth for pth in Path.cwd().iterdir()
            if pth.suffix == '.asm']

หรือถ้าคุณไม่ชอบความเข้าใจในรายการ:

asm_paths = []
for pth in Path.cwd().iterdir():
    if pth.suffix == '.asm':
        asm_pths.append(pth)

Path วัตถุสามารถถูกแปลงเป็นสตริงได้อย่างง่ายดาย


9

นี่คือวิธีที่ฉันทำซ้ำผ่านไฟล์ใน Python:

import os

path = 'the/name/of/your/path'

folder = os.fsencode(path)

filenames = []

for file in os.listdir(folder):
    filename = os.fsdecode(file)
    if filename.endswith( ('.jpeg', '.png', '.gif') ): # whatever file types you're using...
        filenames.append(filename)

filenames.sort() # now you have the filenames and can do something with them

ไม่มีเทคนิคเหล่านี้รับประกันการสั่งซื้อซ้ำใด ๆ

ใช่แล้วทายไม่ถูกสุด ๆ โปรดสังเกตว่าฉันเรียงลำดับชื่อไฟล์ซึ่งสำคัญหากลำดับของไฟล์มีความสำคัญเช่นสำหรับเฟรมวิดีโอหรือการรวบรวมข้อมูลที่ขึ้นอยู่กับเวลา อย่าลืมใส่ดัชนีในชื่อไฟล์ของคุณ!


ไม่เรียงลำดับเสมอ ... im1, im10, im11 ... , im2 ...มิฉะนั้นแนวทางที่มีประโยชน์ from pkg_resources import parse_versionและ filenames.sort(key=parse_version)ทำมัน
Hastur

5

คุณสามารถใช้globเพื่ออ้างอิงไดเรกทอรีและรายการ:

import glob
import os

#to get the current working directory name
cwd = os.getcwd()
#Load the images from images folder.
for f in glob.glob('images\*.jpg'):   
    dir_name = get_dir_name(f)
    image_file_name = dir_name + '.jpg'
    #To print the file name with path (path will be in string)
    print (image_file_name)

ในการรับรายการไดเรกทอรีทั้งหมดในอาร์เรย์คุณสามารถใช้ระบบปฏิบัติการ :

os.listdir(directory)

4

ฉันยังไม่ค่อยพอใจกับการใช้งานนี้ฉันต้องการมีตัวสร้างแบบกำหนดเองที่ทำDirectoryIndex._make(next(os.walk(input_path)))เช่นนั้นคุณสามารถส่งผ่านเส้นทางที่คุณต้องการรายชื่อไฟล์ได้ ยินดีต้อนรับการแก้ไข!

import collections
import os

DirectoryIndex = collections.namedtuple('DirectoryIndex', ['root', 'dirs', 'files'])

for file_name in DirectoryIndex(*next(os.walk('.'))).files:
    file_path = os.path.join(path, file_name)

2

ฉันชอบการใช้scandirคำสั่งที่สร้างไว้ในosห้องสมุด นี่คือตัวอย่างการทำงาน:

import os

i = 0
with os.scandir('/usr/local/bin') as root_dir:
    for path in root_dir:
        if path.is_file():
            i += 1
            print(f"Full path is: {path} and just the name is: {path.name}")
print(f"{i} files scanned successfully.")

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