Сортировка файлов по папкам на PHP
Доброго времени суток! Уверен, что у многих пользователей компьютеров часто, если не всегда, возникает проблема, когда в некоторой папке (например, Загрузки), собирается много файлов, в которых становится трудно разобраться. С подобной ситуацией (в который раз) недавно столкнулся и я: в папке "Загрузки" скопилось много книг и отчетов (более 500 штук) в формате pdf файлов. Благо, большая часть файлов имела осмысленные названия. Вручную перебирать и сортировать эти файлы желания не было, поэтому я написал скрипт, которым делюсь и с Вами.
Обратите внимание, что скрипт далеко не идеальный, поэтому Вам, возможно, придется вносить в некоторые правки самостоятельно. Итак, код:
Файл sortfiles.php
<?php
// режим отладки - файлы не копирует - просто выводит названия файлов, совпадающих с условием
const DEBUG = false;
/**
* Преобразует двумерный массив $folders в одномерный
*
*/
function flattenedFolders(array $folders): array
{
$out = [];
foreach ($folders as $folderName => $folderTags)
{
foreach ($folderTags as $folderTag)
{
$out[$folderTag] = $folderName;
}
}
ksort($out);
return $out;
}
/**
* Возвращает отсортированный список путей к файлам с расширениям, перечисленными в
* массиве $allowedExtensions
*
*/
function getFilesSorted(FilesystemIterator $files, array $allowedExtensions = ['pdf']): array
{
$filePaths = [];
foreach ($files as $filePath)
{
$extensionAllowed = in_array($filePath->getExtension(), $allowedExtensions);
// если расширения файла нет в списке разрешенных - переходим к следующему элементу списка
if(!$extensionAllowed) continue;
$filePaths[] = $filePath->getPathname();
}
sort($filePaths);
return $filePaths;
}
/**
* преобразует имя файла в простой текст
*
*/
function transformFilename(string $fileName): string
{
$fileName = mb_strtolower($fileName);
$replacers = ['_' => ' ', ',' => ' ', '.pdf' => '', '-' => ' ', '.' => ' '];
return strtr($fileName, $replacers);
}
function mcopy(string $from, string $to, bool $debug = false): bool
{
return $debug || copy($from, $to);
}
/**
* Функция, которая выполняет основную работу, сортируя файлы содержащие
* ключевые слова в соответствующие папки
*
*/
function organizeFilesByFolder(array $folders, array $filePaths)
{
$counter = 1;
// проходимся по всем файлам
foreach ($filePaths as $filePath)
{
$foldersCount = count($folders);
$currentFolderNumber = 0;
foreach ($folders as $folderTag => $folderName)
{
$dirName = __DIR__ . "/books/$folderName";
if (!is_dir($dirName)) mkdir($dirName);
$fileName = transformFilename(basename($filePath));
$found = stripos($fileName, $folderTag);
$basename = basename($filePath);
// если название файла содержит ключевое слово
if($found !== false)
{
// копируем файл в соответствующую папку
$copied = mcopy($filePath, $dirName . DIRECTORY_SEPARATOR . $basename, DEBUG);
if($copied) {
if(DEBUG) {
print("[$counter] **[$folderTag]** [$fileName] \\" . PHP_EOL);
}
else
{
print("[$counter] books/$folderName/$basename" . PHP_EOL);
}
$counter++;
}
break;
}
else
{
$currentFolderNumber++;
// если мы достигли последней папки, а ключевое слово так и не найдено в имени файла
if($currentFolderNumber === $foldersCount) {
if(DEBUG)
{
print("[$counter] **[Unsorted]** [$folderTag] [$fileName] \\" . PHP_EOL);
}
else
{
$dirName = __DIR__ . "/books/Unsorted";
if (!is_dir($dirName)) mkdir($dirName);
// копируем файл в папку Unsorted
$copied = mcopy($filePath, $dirName . DIRECTORY_SEPARATOR . $basename, DEBUG);
if($copied) {
print("[$counter] books/Unsorted/$basename" . PHP_EOL);
}
}
$counter++;
}
}
};
}
}
/**
* массив вида: Название_Папки => Массив ключевых слов, которые могут быть в названии файла
*
*/
$folders = [
'Android' => ['android', 'flutter'],
'JS_Frameworks' => ['react', 'vue', 'angular', 'components'],
'JavaScript' => ['js', 'javascript', 'webassembly'],
'PHP' => ['php', 'laravel'],
'Kotlin' => ['kotlin'],
'DotNet' => ['c#', 'sharp', 'csharp', 'net', 'asp'],
'SQL' => ['database', 'mysql', 'postgres', 'sql'],
'SoftArch' => ['architecture', 'архитектур', 'software', 'refactoring', 'api', 'проектиров', 'archi', 'clean', 'pattern', 'object'],
'Artificial' => ['artificial', 'machine', 'science', 'deep', 'learning', 'data'],
'Python' => ['python', 'flask', 'pandas'],
'Linux' => ['bash', 'linux'],
'HtmlCss' => ['css', 'bootstrap', 'wordpress'],
'CPP' => ['c++', 'cpp'],
'Security' => ['secure', 'security', 'exploit', 'openssl', 'osint', 'безопас'],
'NodeJS' => ['node', 'nodejs'],
'Git' => ['git'],
'Go' => ['go', 'golang'],
'Java' => ['java'],
'Http' => ['http', 'nginx'],
'TypeScript' => ['typescript'],
'UI' => ['interfac'],
'Право' => ['закон']
];
// папка в которой лежат неотсортированные документы
const INPUT_DIR = '/home/myrusakov/Загрузки';
// папка в которую будут складываться отсортированные файлы
if(!is_dir('./books')) mkdir('./books');
$iterator = new FilesystemIterator(INPUT_DIR);
$filePaths = getFilesSorted($iterator);
$flattenedFolders = flattenedFolders($folders);
// сортируем файлы
organizeFilesByFolder($flattenedFolders, $filePaths);
Таким образом, после запуска скрипта, рядом с ним в папке books мы получим большое количество подпапок содержащих отсортированные файлы.
-
- Михаил Русаков
Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.