Как разделить папку с 100к TXT файлами на 10 папок по 10к TXT файлов?

Подскажите простой JavaScript/bat скрипт или другой способ, как разделить папку с 100к TXT файлами на 10 папок по 10к TXT файлов?

Вот иллюстрация на примере разбиения массива уникальных 100к текстовиков по 10 штук текстовиков - "попапочно" введите сюда описание изображения


Ответы (2 шт):

Автор решения: Ein

Крайне рекомендую почитать для понимания происходящего:

Использование:

node script.js                    # разделить текущую директорию на 10 папок
node script.js some_folder        # разделить some_folder на 10 папок
node script.js some_folder 123    # разделить some_folder на 123 папок
node script.js some_folder 100 15 # разделить some_folder на 123 папок по 15 файлов

Код(Node.js)

const fs = require('fs');
const path = require('path');

// Получаем название директории и колчество папок
let [dir, dir_count, per_dir_count] = process.argv.slice(2);
dir = path.format({base: dir || '.'});
dir_count = Number(dir_count) || 10;
per_dir_count = Number(per_dir_count) || 0;

// Получем содержимое директории
let list = fs.readdirSync(dir);

// Отсеиваем всё, кроме файлов
list = list.filter(item => fs.lstatSync(path.join(dir, item)).isFile());

// Сортируем
list.sort((a, b) => a.localeCompare(b, undefined, {
    numeric: true
}));

// Cколько должно быть файлов в каждой директории
let files_per_dir = per_dir_count || Math.ceil(list.length / dir_count);

(async () => {
    // Создаём директории
    let creating_dirs = [];
    for (let i = 1; i <= dir_count; i++) {
        let folder = path.join(dir, i.toString());
        // Проверяем существование директории
        let promise = fs.promises
            .access(folder)
            .catch(() => {
                // Если нет, то создаём
                fs.mkdirSync(folder);
            });
        creating_dirs.push(promise);
    }
    // Ждём пока создания
    await Promise.all(creating_dirs);

    // Перемещаем файлы
    let moving_files = [];
    for (var i = 0; i < list.length; i++) {
        let file = list[i];
        // Выбираем нужную папку
        let folder = path.join(
            dir, 
            Math.floor((i / files_per_dir) + 1).toString()
        );

        let promise = fs.promises.rename(
            path.join(dir, file),
            path.join(folder, file)
        );
    }
    // Дожидаемся перемещения
    await Promise.all(moving_files);
})();
→ Ссылка
Автор решения: Daemon-5
REM включим расширенную обработку переменных,
REM чтобы можно было обращаться к ним в цикле
@setlocal enabledelayedexpansion

REM зададим текущим путем каталог обработки
cd /d C:\App\trash

REM зададим начальное значение для номера файла
set /a a=0

REM Запускаем наш цикл, обрабатывая листинг всех не-каталогов файлов. 
REM Значение текущего имени файла помещаем в переменную %%i
for /f "tokens=*" %%i in ('dir /a-d /b') do (

REM Увеличиваем порядковый номер файла,
REM а в переменной !b! храним номер каталога
set /a "a+=1", b=!a!/10

REM создаем каталог, игнорируя все сообщения
md !b! 2>nul

REM перемещаем текущий файл (по имени) в текущий каталог
move "%%i" !b!

REM конец цикла
)

REM выключаем расширенную обработку
@endlocal

P.S. Скрытые и системные файлы в листинг не попадут. Если работать с UNC-путем, то проще "замапить" его в логический диск, чтобы не усложнять скрипт (который должен уложиться в 10-минутную обработку заявленного количества файлов).

P.S.S. Проверка прав доступа к ресурсу и наличия блокировок файла (мешающих перемещению) - все это ложится на плечи пользователя скрипта.

→ Ссылка