PHP: заменяем для нужных типов файлов в дереве папок что угодно на что угодно
Мне было нужно удалить кучу нуль-терминаторов, помещаемую софтиной в конце каждого создаваемого файла для "выравнивания" их размеров до кластера (и попробуй найди потом самые маленькие файлы?!), но подумал, что проблема вообще распространена:
- есть много файлов с некоторым типом или типами;
- они могут располагаться во вложенных папках, в том числе, с "неправильными" для не-виндоузовских систем именами файлов, например, содержащими кириллицу и пробелы;
- требуется найти во всех файлах некую строку или байт(ы), возможно, по гибкому шаблону поиска, содержащему регулярные выражения, а затем заменить их другой строкой (возможно, пустой), байтами или шаблоном, построенным по найденному регулярным выражением содержимому.
Мне показалось быстрее всего сделать решение на PHP, которое я выполнил на локалхосте XAMPP с PHP8 под актуальной сборкой Windows 10. В сущности, я просто взял обход дерева папок отсюда плюс этот совет из своей коллекции.
Строки поиска и замены настраиваются прямо внутри функции searchAndReplace
, а путь к файлам и допустимые
типы файлов - в начале скрипта. Наверное, можно было бы "прикрутить" интейрфейс, но оставим это тем, кому подобный сервис может понадобиться периодически, а не разово.
Полезной может оказаться и функция getFileName
, получающая имя файла с кириллицей и пробелами на локалхосте Windows. Ниже показан полный исходник скрипта, успешно решившего мою задачу, его можно выполнить как файл типа .php в кодировке Юникода UTF-8.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>clearFiles</title> </head> <body> <p> </p> <?php $dir = './pgn'; //путь к нужной папке без слэша в конце, например, начать с текущей будет '.' $types = 'pgn'; //типы файлов, можно несколько, например, 'jpg|jpeg|png|gif' function getFileName ($dir, $value) { //Получение имени файла с кириллицей и пробелами - здесь для Windows $f = iconv('UTF-8', 'cp1251', $dir.'/'.$value); $f = str_replace('%28','(',$f); $f = str_replace('%29',')',$f); $f = str_replace('+','%20',$f); return $f; } function searchAndReplace ($dir, $types) { $result = array(); $cdir = scandir ($dir); foreach ($cdir as $value) { if (is_dir ($dir.'/'.$value) and !preg_match("/^\..*$/",$value)) { //папка, но не начинается с точки $result[$dir.'/'.$value] = searchAndReplace ($dir.'/'.$value, $types); } else if (preg_match("/^.*\.(".$types.")$/i",$value)) { //не папка, и имя соответствует маске $resultstr = $dir.'/'.$value; $file = @file_get_contents(getFileName($dir, $value)); if ($file === false) { $resultstr .= ' (ошибка чтения)'; } else { $bytesWrote = file_put_contents ( getFileName($dir, $value), preg_replace_callback( "/\x{00}/", //строка поиска, можно регулярку, например, "/[a-zA-Z]+/" function ($matches) { return ""; }, //строка замены, можно возвращать и выражения //со стандартными функциями или включающие найденное, например, strtoupper($matches) $file) ); if ($bytesWrote === false) { $resultstr .= ' (ошибка записи)'; } } $result[] = $resultstr; } } return $result; } function showList ($files) { $s = ''; foreach ($files as $path => $file) { if (is_array($files[$path])) //путь к папке будет заголовком $s .= "\n".'<h3>'.$path.'</h3>'.showList ($files[$path]); else { $s .= $files[$path].'<br>'."\n"; } } return $s."\n"; } $files = searchAndReplace ($dir, $types); //получить файлы и сделать замену asort ($files); //файлы текущей папки должны оказаться впереди echo showList ($files); //показать отсортированный список ?> </body> </html>
25.04.2021, 15:36 [928 просмотров]