БлогNot. PHP: заменяем для нужных типов файлов в дереве папок что угодно на что угодно

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 просмотров]


теги: textprocessing windows программирование php

К этой статье пока нет комментариев, Ваш будет первым