2010-06-24 15 views
5

मैं पाइथन को कमांड लाइन स्क्रिप्टिंग प्रतिस्थापन के रूप में उपयोग करना सीखना चाहता हूं। मैंने अतीत में अजगर के साथ कुछ समय बिताया लेकिन यह थोड़ी देर हो गया है। ऐसा लगता है कि यह इसके दायरे में है।पाइथन के माध्यम से किसी फ़ोल्डर में सभी फ़ाइलों में एक खोज-और-प्रतिस्थापन करें?

मेरे पास एक फ़ोल्डर में कई फ़ाइलें हैं जिन्हें मैं खोज-और-प्रतिस्थापन करना चाहता हूं, उन सभी के भीतर। मैं इसे एक अजगर लिपि के साथ करना चाहता हूं।

उदाहरण के लिए, "foo" के सभी उदाहरणों को खोजें और बदलें "foobar"।

उत्तर

2

आम तौर पर मैं पुराने perl -pi -e 's/foo/foobar/' इस के लिए बाहर कोड़ा चाहते हैं, लेकिन आप अजगर चाहते हैं:

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) 

और अगर आप विंडोज पर हैं, तो आप os.rename(tempfile, file) से पहले एक os.remove(file) जोड़ने की आवश्यकता होगी।

+0

इसके अलावा, यह डाल करने के लिए अच्छा हो सकता है यह सत्यापित करने के लिए एक छोटी सी जांच में कि 'tempfile' पहले से मौजूद नहीं है ... –

+0

ऐसा लगता है। क्या temp फ़ाइल बनाने का कार्य बस इतना है कि यदि अनुमति पर्याप्त नहीं है, तो भी हम कार्रवाई कर सकते हैं? उस स्थिति में, निकालें और नाम या तो काम नहीं करेगा, सही? – fruit

+0

tempfile यह सुनिश्चित करता है कि हम वास्तविक फ़ाइल को बहुत जल्दी ओवरराइट नहीं करते हैं और इसलिए कि हम बड़ी फ़ाइल पर बहुत सारी मेमोरी का उपयोग नहीं करते हैं (ऐसा करने का नाइव तरीका ऐसा कुछ होगा: 'data = open (file) .read(); डेटा = _replace_re.sub ("foobar", डेटा); खोलें (फ़ाइल, "डब्ल्यू")। लिखें (डेटा) ', लेकिन यह बहुत सारी मेमोरी का उपयोग करेगा और, यदि कंप्यूटर आधे रास्ते से दुर्घटनाग्रस्त हो गया है 'लिखना', आप अन-लिखित डेटा को खो देंगे) –

1

मैंने इसके माध्यम से काम किया और ऐसा लगता है, लेकिन किसी भी त्रुटि को इंगित किया जा सकता है।

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

इस पर एक विस्तार फ़ोल्डरों के भीतर फ़ोल्डर में स्थानांतरित करना होगा।

+0

आप जो करना चाहते हैं वह बदलना है 'replaceAll (फ़ाइल, "काला", "सफेद")' - जैसा कि यह है कि यदि आपके पास कभी 'somedir है/blackdir/blackfile.txt' तो आपको 'somedir/whitedir/whitefile.txt' मिलेगा।बेशक आप इसे चाहते हैं, इस मामले में इसे छोड़ दें कि यह आपके पास कैसे है। –

+0

यह फ़ंक्शन फ़ाइलों का नाम क्यों देगा? यह लाइन से लाइन खोज रहा है .. – fruit

5

स्टैक ओवरव्लो में आपका स्वागत है। चूंकि आप स्वयं को सीखना चाहते हैं (+1) मैं आपको कुछ पॉइंटर्स दूंगा।

सभी फ़ाइलों को प्राप्त करने के लिए os.walk() देखें।

फिर फ़ाइलों में प्रत्येक पंक्ति पर पुनरावृत्त करें (for line in currentfile: यहां काम में आता है)। एक स्मार्ट की जगह आप एक परिणाम के रूप foofoobar चाहते हैं) या -

अब तुम अगर आप चाहते हैं एक "बेवकूफ" पता करने की जरूरत की जगह (लगता है/प्रत्येक foo की जगह भले ही वह एक शब्द के बीच में है (जैसे कि foobar?।

पूर्व के लिए, str.replace() को देखने के बाद के लिए, re.sub() को देखो और क्या r'\bfoo\b' साधन यह पता लगाने।

+0

बहुत अच्छा, धन्यवाद! नए कार्यों के बारे में सीखना (os.walk()) हमेशा अच्छा होता है। क्या यह उपनिर्देशिकाओं को भी पार करता है? मुझे लगता है कि आपका लिंक मुझे बताएगा। – fruit

+0

हाँ यह करता है, और हाँ यह करता है :) –

0

इस एक विकल्प है, जब से तुम आपको प्रस्तुत विभिन्न पायथन समाधान। सबसे अधिक उपयोगी उपयोगिता है (मेरे अनुसार), यूनिक्स/विंडोज में, जीएनयू को खोजने के लिए आदेश और प्रतिस्थापन उपकरण जैसे sed/awk है। आईल्स (रिकर्सिवली) और प्रतिस्थापन करते हैं, इस तरह की एक साधारण कमांड चाल है (वाक्यविन्यास स्मृति से आता है और परीक्षण नहीं किया जाता है)। यह सब पाठ फ़ाइलें खोजने के लिए और एक ही समय में शब्द 'नई' करने के लिए "पुराने" उनकी सामग्री में परिवर्तन करना हो, बैकअप के लिए sed का उपयोग मूल फाइलों कहते हैं ...

$ find /path -type f -iname "*.txt" -exec sed -i.bak 's/old/new/g' "{}" +; 
संबंधित मुद्दे