วนซ้ำไดเรกทอรีต่างๆด้วย Python


157

ฉันจำเป็นต้องทำซ้ำผ่านไดเรกทอรีย่อยของไดเรกทอรีที่กำหนดและค้นหาไฟล์ ถ้าฉันได้รับไฟล์ฉันต้องเปิดมันและเปลี่ยนเนื้อหาและแทนที่ด้วยบรรทัดของตัวเอง

ฉันลองสิ่งนี้:

import os

rootdir ='C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        f=open(file,'r')
        lines=f.readlines()
        f.close()
        f=open(file,'w')
        for line in lines:
            newline = "No you are not"
            f.write(newline)
        f.close()

แต่ฉันได้รับข้อผิดพลาด ผมทำอะไรผิดหรือเปล่า?


12
"ข้อผิดพลาด" - ข้อผิดพลาดใด ๆ โดยเฉพาะอย่างยิ่ง?
Daniel Roseman

1
คุณช่วยอธิบายหน่อยเกี่ยวกับสิ่งที่คุณหวังว่าจะทำกับไฟล์ / ไดเร็กตอรี่เมื่อคุณผ่านมันไปตามที่ตั้งใจไว้? นอกจากนี้โปรดระบุรายละเอียดข้อผิดพลาด
ChrisProsser

1
ข้อความแสดงข้อผิดพลาดที่ฉันได้รับคือไม่พบไฟล์ cool.txt ในโฟลเดอร์ทดสอบของฉันฉันมีโฟลเดอร์อื่นที่เรียกว่า src และในโฟลเดอร์ src ฉันมีโฟลเดอร์อื่นที่เรียกว่า main ในโฟลเดอร์นี้ฉันมี cool.txt
Wolf

4
คุณสามารถเขียนข้อผิดพลาดในคำถามได้ไหม มันเกินกว่าที่น่ารำคาญและไม่จำเป็นต้องอ่านความคิดเห็นเพื่อค้นหามัน
Charlie Parker

1
ในอีกหนึ่งปีต่อมาฉันไม่อยากจะเชื่อเลยว่าฉันกลับมาขอให้มีการโพสต์ข้อผิดพลาด? @Wolf
Charlie Parker

คำตอบ:


300

การเดินผ่านไดเรกทอรีใช้งานได้จริงตามที่คุณได้กำหนดรหัสไว้ หากคุณแทนที่เนื้อหาของวงภายในด้วยง่ายprintคำสั่งคุณจะเห็นว่าแต่ละไฟล์พบ:

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print os.path.join(subdir, file)

หากคุณยังคงได้รับข้อผิดพลาดเมื่อเรียกใช้ข้างต้นโปรดระบุข้อความข้อผิดพลาด


อัปเดตสำหรับ Python3

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print(os.path.join(subdir, file))

1
C: / Users / sid / Desktop / test \ src \ app / cool.txt C: / Users / sid / Desktop / test \ src \ app / woohoo.txt Ya ในคำสั่ง open code ของฉันฉันคิดว่าฉันต้อง ให้พา ธ สัมบูรณ์ไปยังไฟล์ import os rootdir = 'C: / Users / spemmara / Desktop / ทดสอบ / src / app /' สำหรับ subdir, dirs, ไฟล์ใน os.walk (rootdir): สำหรับไฟล์ในไฟล์: f = open (subdir + '/' + ไฟล์ , 'r') lines = f.readlines () f.close () f = open (subdir + '/' + ไฟล์, 'w') สำหรับบรรทัดในบรรทัด: newline = "เฮ้ฉันรู้" f.write (ขึ้นบรรทัดใหม่) f.close () ขอบคุณมาก แก้ไขแล้ว
Wolf

3
Hi! โปรดทราบว่า "พิมพ์" ในหลาม 3 ต้องใช้วงเล็บมิฉะนั้นจะส่งกลับข้อผิดพลาดทางไวยากรณ์ หวังว่านี่จะช่วยได้!
Tommaso Di Noto

14

วิธีการกลับไฟล์ทั้งหมดในไดเรกทอรีย่อยหนึ่งคือการใช้โมดูลแนะนำใน Python 3.4 ซึ่งมีวัตถุวิธีการที่มุ่งเน้นถึงการจัดการเส้นทางระบบแฟ้ม (Pathlib ยังมีอยู่บน Python 2.7 ผ่านโมดูล pathlib2 บน PyPi ):pathlib

from pathlib import Path

rootdir = Path('C:/Users/sid/Desktop/test')
# Return a list of regular files only, not directories
file_list = [f for f in rootdir.glob('**/*') if f.is_file()]

# For absolute paths instead of relative the current dir
file_list = [f for f in rootdir.resolve().glob('**/*') if f.is_file()]

ตั้งแต่ Python 3.5 globโมดูลยังรองรับการค้นหาไฟล์แบบเรียกซ้ำ:

import os
from glob import iglob

rootdir_glob = 'C:/Users/sid/Desktop/test/**/*' # Note the added asterisks
# This will return absolute paths
file_list = [f for f in iglob('**/*', recursive=True) if os.path.isfile(f)]

file_listจากทั้งวิธีการข้างต้นสามารถซ้ำมากกว่าโดยไม่จำเป็นต้องห่วงซ้อนกัน:

for f in file_list:
    print(f) # Replace with desired operations

1
สิ่งที่ดีกว่าสำหรับ Python 3.6 คืออะไร
PhoenixDev

@PhoenixDev ฉันไม่เคยได้ยินวิธีการหนึ่งที่แนะนำโดยทั่วไป ฉันชอบใช้pathlibตัวเองเป็นส่วนใหญ่เพราะฉันชอบวิธีการเชิงวัตถุ - ไวยากรณ์ มีความแตกต่างอื่น ๆ เช่นไลบรารีพา ธ ส่งคืนคลาสพา ธ ที่เฉพาะเจาะจงมากกว่าสตริงและฟังก์ชั่นที่มีอยู่แตกต่างกันระหว่างไลบรารี (เช่นos.path.expanduser('~')vs Path.home()) เรียกดูเอกสารและดูว่าคุณต้องการแนวทางแบบใด
joelostblom

แทนการเพิ่ม**ในรูปแบบ glob rglobคุณสามารถใช้
Georgy

12

ในฐานะของ2020 , glob.iglob(path/**, recursive=True)ดูเหมือนว่าส่วนใหญ่pythonicวิธีการแก้ปัญหาเช่น:

import glob, os

for filename in glob.iglob('/pardadox-music/**', recursive=True):
    if os.path.isfile(filename): # filter dirs
        print(filename)

เอาท์พุท:

/pardadox-music/modules/her1.mod
/pardadox-music/modules/her2.mod
...

หมายเหตุ:
1 - glob.iglob

glob.iglob(pathname, recursive=False)

ส่งคืนตัววนซ้ำซึ่งให้ค่าเหมือนกันglob()โดยไม่ต้องเก็บค่าทั้งหมดพร้อมกัน

2 - หาก recursive เป็นTrueรูปแบบ'**'จะตรงกับไฟล์ใด ๆ และเป็นศูนย์หรือมากกว่าและdirectoriessubdirectories

3 - หากไดเรกทอรีมีไฟล์ที่ขึ้นต้นด้วย  .พวกเขาจะไม่ถูกจับคู่โดยค่าเริ่มต้น ตัวอย่างเช่นพิจารณาไดเรกทอรีที่มี  card.gif และ.card.gif:

>>> import glob
>>> glob.glob('*.gif') ['card.gif'] 
>>> glob.glob('.c*')['.card.gif']

4 - คุณยังสามารถใช้rglob(pattern)ซึ่งเหมือนกับการโทร  glob() โดย**/เพิ่มไว้ด้านหน้ารูปแบบสัมพัทธ์ที่กำหนด


1
โซลูชันpythonicนี้ไม่ได้แสดงรายการไฟล์ที่ซ่อนอยู่ (aka dotfiles) ในขณะที่ไฟล์ที่ยอมรับนั้น
ashrasmun

@ashrasmun สิ่งที่คุณพูดถึงมีการอธิบายอย่างดีในdocs.python.org/3/library/glob.html
CONVid19
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.