LINUX.ORG.RU

Как быстро заменить строку в миллионе файлов .php?

 ,


0

1

Всем привет,

Нужно решение - заменить строчку кода в миллионе файлов .php (строчка во всех файлах одинаковая естественно).

Т.е. есть 1кк+ файлов .php которые содержат небольшую строку, которую нужно заменить везде.

Решений много, но замена идет очень долго. Кто-то может посоветовать самое быстрое решение? Спасибо.

Ответ на: комментарий от aureliano15

Идеальный вариант - это всё затарить

Это не вариант, это тупняк. Для тех кто в танке - проблема с поиском файлов _в первый раз_, а не с доступом. Вариант с затариванием будет не быстрее, а медленнее, т.к. тратится время на тар и разтар обратно.

no-such-file ★★★★★
()
Ответ на: комментарий от aureliano15

Аргументы -exec заканчиваются «\;»

Когда над множеством файлов нужно одновременно произвести однотипную операцию, exec лучше завершать «+» — так все найденные файлы будут переданы одним пулом. Только нужно следить, чтобы количество аргументов не вылезло за ограничения.

beresk_let ★★★★★
()
Ответ на: комментарий от no-such-file

Очень много обсуждений, очень мало экспериментов. Все равно нельзя заранее сказать что окажется быстрее, сколько людей, столько и мнений. Запустить десяток разных вариантов по тысяче файлов, сравнить время и выбрать лучший.

vaddd ★☆
()
Ответ на: комментарий от beresk_let

Оно вроде как за всем следит само как xargs. Правда с пробелами в путях проблема, так что лучше использовать xargs. Вообще удивительно насколько этот -exec бесполезен из-за пробелов.

anonymous
()

Миллион файлов - это очень мало.

Файлы то большие хоть? Если меньше 64к - можно банально RecursiveDirectoryIterator + file_get_contents + preg_replace, если счётчик реплейса ненулевой - file_put_contents. Скрипт в десять строчек максимум, даже с учётом контроля ошибок.

AlexAT
()
Ответ на: комментарий от no-such-file

Всем большое спасибо за участие! Вот эта команда успешно справляется с задачей:

find -type f -name '*.php' -print0 | xargs -0 -P 8 sed -i -- 's/foo/bar/g'
Попробую еще другие варианты, т.к. автозамена нужна в нескольких папках, отпишусь по результатам.

Merca709
() автор топика
Ответ на: комментарий от Merca709

Вот эта команда успешно справляется с задачей:

Если: a) строка замены не длиннее исходной и б) файлы поместятся в память, то я такое решаю простенькой утилиткой, написал ради прикола за несколько минут: mmap-им файл, ищем в памяти исходную строку, заменяем, если строка короче, то ещё надо memmove. Быстрее сделать невозможно.

vodz ★★★★★
()
Ответ на: комментарий от anonymous

Правда с пробелами в путях проблема

Какая проблема?

anonymous
()
Ответ на: комментарий от no-such-file

Шло несколько часов, думаю часа 4, самое точное время не засек. Буду еще тестить дальше - отпишусь. Очень круто, что это решение в итоге сработало.

Merca709
() автор топика
27 февраля 2018 г.
Ответ на: комментарий от Merca709

Есть сайт с кучей абсолютных путей в файлах php, tpl и пр. Делаю так:

find -type f -name \*.tpl -exec sed -i -r «s|'\/var\/www\/site.ru\/www\/|$_SERVER['DOCUMENT_ROOT'].'\/|g» {} \;
Получаю в файлах
php include(['DOCUMENT_ROOT'].'/compare/optprice.php')
Т.е. $_SERVER куда-то теряется. Где ошибка?.. Пробовал экранировать этот самый $_SERVER - не помогает. Глобально задача в том, чтобы вычистить на сайте абсолютные пути вида http://site.ru и /var/www/site.ru/ и привести все к относительным.

MrRitm
()
Ответ на: комментарий от MrRitm

Помучавшись какое-то время нашел решение. Надо было так

find -type f -name \*.* -exec sed -i -r 's|"\/var\/www\/site.ru\/www\/|$\_SERVER['DOCUMENT_ROOT']."\/|g' {} \;
В итоге все получилось как надо.

MrRitm
()
Ответ на: комментарий от no-such-file

Что-то похожее делал. На 10000 сишных файлах отрабатывает за минуту в 4 потока. При этом где-то 20% от 100% процессорного времени занято ядром. Но я скармливал по 5 файлов (xargs -n 5). Так же пробовал питон с компилированым регекспом для замены, справляется примерно за тоже время в один поток. Но проще работать с седом, чем заботиться о недопущении тепловой сметри вселенной. И это было давно и неправда.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.