2010-06-24 28 views
5

Tôi muốn học cách sử dụng python như là một thay thế kịch bản dòng lệnh. Tôi đã dành thời gian với python trong quá khứ nhưng nó đã được một thời gian. Điều này dường như nằm trong phạm vi của nó.Thực hiện tìm kiếm và thay thế trên tất cả các tệp trong một thư mục thông qua python?

Tôi có một số tệp trong thư mục mà tôi muốn thực hiện tìm kiếm và thay thế trên tất cả các tệp đó. Tôi muốn làm điều đó với một kịch bản python.

Ví dụ: tìm kiếm và thay thế tất cả các phiên bản "foo" bằng "foobar".

Trả lời

2

Thông thường tôi muốn whip ra cũ perl -pi -e 's/foo/foobar/' cho điều này, tuy nhiên nếu muốn Python:

import os 
import re 
_replace_re = re.compile("foo") 
for dirpath, dirnames, filenames in os.walk("directory/"): 
    for file in filenames: 
     file = os.path.join(dirpath, file) 
     tempfile = file + ".temp" 
     with open(tempfile, "w") as target: 
      with open(file) as source: 
       for line in source: 
        line = _replace_re.sub("foobar", line) 
        target.write(line) 
     os.rename(tempfile, file) 

Nếu bạn đang ở trên Windows, bạn sẽ cần phải thêm một os.remove(file) trước os.rename(tempfile, file).

+0

Ngoài ra, có thể tốt trong một kiểm tra nhỏ để xác minh rằng 'tempfile' chưa tồn tại… –

+0

Điều này có vẻ hợp lý. Là hành động tạo tệp tạm thời chỉ vì vậy nếu quyền không đủ, chúng tôi vẫn có thể thực hiện hành động? Trong trường hợp đó, việc xóa và đổi tên sẽ không hoạt động, đúng không? – fruit

+0

Tempfile đảm bảo rằng chúng tôi không ghi đè lên tệp thật quá sớm và do đó chúng tôi không sử dụng nhiều bộ nhớ trên một tệp lớn (cách thức để thực hiện nó sẽ giống như: 'data = open (tệp) .read(); data = _replace_re.sub ("foobar", dữ liệu); mở (tập tin, "w"). write (dữ liệu) ', nhưng điều đó sẽ sử dụng rất nhiều bộ nhớ và, nếu máy tính bị rơi một nửa thông qua 'write', bạn sẽ mất dữ liệu chưa được viết) –

1

Tôi đã làm việc thông qua nó và điều này dường như làm việc, nhưng bất kỳ lỗi nào có thể được chỉ ra sẽ là tuyệt vời.

import fileinput, sys, os 

def replaceAll(file, findexp, replaceexp): 
    for line in fileinput.input(file, inplace=1): 
     if findexp in line: 
      line = line.replace(findexp, replaceexp) 
     sys.stdout.write(line) 

if __name__ == '__main__': 
    files = os.listdir("c:/testing/") 
    for file in files: 
     newfile = os.path.join("C:/testing/", file) 
     replaceAll(newfile, "black", "white") 

việc mở rộng này sẽ chuyển sang thư mục trong thư mục.

+0

Những gì bạn có thể muốn làm là thay đổi thành' replaceAll (tập tin, "đen", "trắng") '- vì nó là viết tắt của bạn nếu bạn có' somedir/blackdir/blackfile.txt' sau đó bạn sẽ nhận được 'somedir/whitedir/whitefile.txt'.Trừ khi tất nhiên bạn muốn điều đó, trong trường hợp đó để lại nó chỉ là cách bạn có nó. –

+0

Tại sao chức năng này đổi tên tệp? Nó đang tìm kiếm nó theo từng dòng .. – fruit

5

Chào mừng bạn đến với StackOverflow. Vì bạn muốn tự học (1) Tôi sẽ chỉ cung cấp cho bạn một vài gợi ý.

Khám phá os.walk() để xem tất cả các tệp.

Sau đó lặp qua mỗi dòng trong các tệp (for line in currentfile: có ích ở đây).

Bây giờ bạn cần biết nếu bạn muốn thay thế "ngu ngốc" (tìm/thay thế mỗi foo ngay cả khi nó ở giữa một từ (ví dụ foobar - bạn có muốn foofoobar kết quả không?) Hoặc thay thế thông minh.

đối với cựu, nhìn vào str.replace(), cho sau này, nhìn vào re.sub() và tìm ra những gì r'\bfoo\b' phương tiện.

+0

Rất tuyệt, cảm ơn! Tìm hiểu về các hàm mới (os.walk()) luôn tốt. Nó có đi qua các thư mục con không? Tôi giả sử liên kết của bạn sẽ cho tôi biết. – fruit

+0

Có, và có nó :) –

0

đây là một sự thay thế, kể từ khi bạn có giải pháp Python khác nhau giới thiệu cho bạn. các tiện ích hữu ích nhất (theo tôi), trong Unix/Windows, GNU tìm lệnh và các công cụ thay thế như sed/awk để tìm kiếm f iles (đệ quy) và làm thay thế, một lệnh đơn giản như thế này hiện các trick (cú pháp đến từ bộ nhớ và không được thử nghiệm). điều này cho biết tìm tất cả các tệp văn bản và thay đổi từ "cũ" thành "mới" trong nội dung của chúng, đồng thời, sử dụng sed để sao lưu các tệp gốc ...

$ find /path -type f -iname "*.txt" -exec sed -i.bak 's/old/new/g' "{}" +; 
Các vấn đề liên quan