Новости

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

Сортировка файлов по папкам на 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 для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Back to top button