Ответ 1
Поместите весь этот код в файл с именем mass_replace
. В Linux или Mac OS X вы можете сделать chmod +x mass_replace
, а затем просто запустить это. В Windows вы можете запустить его с помощью python mass_replace
, за которым следуют соответствующие аргументы.
#!/usr/bin/python
import os
import re
import sys
# list of extensions to replace
DEFAULT_REPLACE_EXTENSIONS = None
# example: uncomment next line to only replace *.c, *.h, and/or *.txt
# DEFAULT_REPLACE_EXTENSIONS = (".c", ".h", ".txt")
def try_to_replace(fname, replace_extensions=DEFAULT_REPLACE_EXTENSIONS):
if replace_extensions:
return fname.lower().endswith(replace_extensions)
return True
def file_replace(fname, pat, s_after):
# first, see if the pattern is even in the file.
with open(fname) as f:
if not any(re.search(pat, line) for line in f):
return # pattern does not occur in file so we are done.
# pattern is in the file, so perform replace operation.
with open(fname) as f:
out_fname = fname + ".tmp"
out = open(out_fname, "w")
for line in f:
out.write(re.sub(pat, s_after, line))
out.close()
os.rename(out_fname, fname)
def mass_replace(dir_name, s_before, s_after, replace_extensions=DEFAULT_REPLACE_EXTENSIONS):
pat = re.compile(s_before)
for dirpath, dirnames, filenames in os.walk(dir_name):
for fname in filenames:
if try_to_replace(fname, replace_extensions):
fullname = os.path.join(dirpath, fname)
file_replace(fullname, pat, s_after)
if len(sys.argv) != 4:
u = "Usage: mass_replace <dir_name> <string_before> <string_after>\n"
sys.stderr.write(u)
sys.exit(1)
mass_replace(sys.argv[1], sys.argv[2], sys.argv[3])
EDIT: я изменил приведенный выше код из исходного ответа. Есть несколько изменений. Во-первых, mass_replace()
теперь вызывает re.compile()
, чтобы предварительно скомпилировать шаблон поиска; во-вторых, чтобы проверить, какое расширение имеет файл, мы теперь передаем кортеж расширений файлов .endswith()
, а не вызываем .endswith()
три раза; в-третьих, теперь он использует оператор with
, доступный в последних версиях Python; и, наконец, file_replace()
теперь проверяет, найден ли шаблон в файле и не переписывает файл, если шаблон не найден. (Старая версия будет переписывать каждый файл, изменяя временные метки, даже если выходной файл был идентичен входному файлу, это было неэлегантно.)
EDIT: я изменил это значение на значение по умолчанию, чтобы заменить каждый файл, но с одной строкой, которую вы можете редактировать, чтобы ограничить ее конкретными расширениями. Я думаю, что заменять каждый файл является более полезным по умолчанию. Это можно расширить с помощью списка расширений или имен файлов, которые нельзя коснуться, варианты, чтобы сделать регистр нечувствительным и т.д.
EDIT: в комментарии @asciimo указал на ошибку. Я отредактировал это, чтобы исправить ошибку. str.endswith()
документируется, чтобы принять кортеж строк, чтобы попытаться, но не список. Исправлена. Кроме того, я сделал пару функций, которые принимают необязательный аргумент, чтобы вы могли пройти в кортеже расширений; это должно быть довольно легко изменить, чтобы принять аргумент командной строки, чтобы указать, какие расширения.