Сортировка файлов по папкам на PHP

0

Сортировка файлов по папкам на 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 мы получим большое количество подпапок содержащих отсортированные файлы.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.