2010-06-24 13 views
5

Mi piacerebbe imparare a usare python come una sostituzione di script da riga di comando. Ho passato un po 'di tempo con Python in passato ma è passato un po' di tempo. Questo sembra essere nella sua portata.Esegui una ricerca e sostituisci tutti i file in una cartella tramite python?

Ho diversi file in una cartella su cui voglio eseguire una ricerca e sostituzione, all'interno di tutti. Mi piacerebbe farlo con uno script python.

Ad esempio, cercare e sostituire tutte le istanze di "foo" con "foobar".

risposta

2

Normalmente avrei tirate fuori il vecchio perl -pi -e 's/foo/foobar/' per questo, ma se si vuole 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) 

E se siete su Windows, è necessario aggiungere un os.remove(file) prima della os.rename(tempfile, file).

+0

Inoltre, potrebbe essere buono per mettere in un piccolo controllo per verificare che il 'tempfile' non esiste già ... –

+0

Questo sembra avere un senso. L'atto di creare il file temporaneo è sufficiente, quindi se le autorizzazioni non bastano, possiamo comunque eseguire l'azione? In tal caso, rimuovere e rinominare non funzionerà, corretto? – fruit

+0

Il tempfile si assicura che non sovrascriveremo il file reale troppo presto e che non usiamo molta memoria su un file di grandi dimensioni (il modo migliore per farlo sarebbe qualcosa come: 'data = open (file) .read(); data = _replace_re.sub ("foobar", data); open (file, "w"). write (data) ', ma che userebbe molta memoria e, se il computer si è schiantato a metà il 'scrivi', perdi i dati non scritti) –

1

Ho lavorato su di esso e questo sembra funzionare, ma qualsiasi errore che può essere evidenziato sarebbe fantastico.

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

un'espansione su questo sarebbe spostare in cartelle all'interno di cartelle.

+0

Quello che potresti voler fare è cambiarlo in' replaceAll (file, "black", "white") '- così com'è se tu avessi" somedir "/blackdir/blackfile.txt' allora otterrai 'somedir/whitedir/whitefile.txt'.A meno che non lo si voglia, in tal caso lasciatelo come lo avete. –

+0

Perché questa funzione dovrebbe rinominare i file? Lo sta cercando riga per riga .. – fruit

5

Benvenuti in StackOverflow. Dal momento che vuoi imparare te stesso (+1) ti darò solo alcune indicazioni.

Verificare os.walk() per ottenere tutti i file.

Quindi eseguire l'iterazione su ciascuna riga nei file (for line in currentfile: è utile qui).

Ora è necessario sapere se si desidera una "stupida" sostituire (find/sostituire ogni foo anche se è nel mezzo di una parola (ad esempio foobar - Vuoi foofoobar come risultato) o in una smart sostituire?.

per il primo, guarda str.replace(), per quest'ultimo, guarda re.sub() e capire cosa r'\bfoo\b' mezzi.

+0

Molto bello, grazie! L'apprendimento di nuove funzioni (os.walk()) è sempre buono. Attraversa anche le sottodirectory? Presumo che il tuo link me lo dirà. – fruit

+0

Sì, sì e sì :) –

0

si tratta di un'alternativa, dal momento che si dispone di varie soluzioni Python presentato a voi. l'utilità più utile (secondo me), in Unix/Windows, è il comando GNU find e gli strumenti di sostituzione come sed/awk per cercare f iles (ricorsivamente) e fai la sostituzione, un semplice comando come questo fa il trucco (la sintassi viene dalla memoria e non testata). questo dice trovare tutti i file di testo e modificare la parola "vecchio" al "nuovo" nel loro contenuto, allo stesso tempo, utilizzare sed eseguire il backup dei file originali ...

$ find /path -type f -iname "*.txt" -exec sed -i.bak 's/old/new/g' "{}" +; 
Problemi correlati