Как остановиться после того, как скрипт создал несколько папок и выбрал файлы случайным образом?

@Mofi очень помог мне в этом моем ответе Как упорядочить файлы по папкам?

Сейчас попробовал себе добавить фичу, работает, но за респект за эту замечательную работу Мофи, думаю, есть более профессиональный способ сделать.

Мне нужно, чтобы пакет остановился после создания нескольких папок.

Допустим, у меня есть 100000 .mp4 файлов в основном каталоге. Скрипт теперь обрабатывает их все вместе.

Например, мне нужно использовать всего 1200 файлов и сгруппировать их в 120 папок. Я могу сделать это сейчас с FoldersInFolders=120 и FilesInFolder=10. Проблема в том, что после завершения Canal-1 он продолжается с Canal-2 до Canal-10 и т. д., пока все 100000 файлов MP4 не будут перемещены в каталоги, а я этого не хочу. Я хочу остановиться после 120 папок в целом и обработать только 1200 из 100000 файлов MP4, которые у меня есть в моей основной папке.

Я добавил следующие две строки:

set "MaxTotalFolders=120"
if "!VideosIndex!"= = "%MaxTotalFolders%" exit /b 0 
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FilesInFolder=10"
set "FoldersInFolders=120"
set "MaxTotalFolders=120"

for %%# in ("%USERPROFILE%\Videos" "D:\Videos" "F:\Temp\Videos" "\\MyNAS\Videos") do (
    pushd %%# 2>nul
    if not errorlevel 1 (
        if not exist "*!*.mp4" (
            setlocal EnableDelayedExpansion
            set "FileCount=%FilesInFolder%"
            set "CanalIndex=0"
            set "VideosIndex=%FoldersInFolders%
            for /F "eol=| delims = " %%I in ('dir *.mp4 /A-D /B /ON 2^>nul') do (
                if !FileCount! == %FilesInFolder% (
                    set FileCount=0
                    if !VideosIndex! == %FoldersInFolders% (
                        set /A CanalIndex+=1
                        set VideosIndex=1
                    ) else set /A VideosIndex+=1
                    set "TargetFolder=Canal-!CanalIndex!\Videos-!VideosIndex!"
                    md "!TargetFolder!" 2>nul
                    if "!VideosIndex!"= = "%MaxTotalFolders%" exit /b 0 
                )
                move /Y "%%I" "!TargetFolder!\" >nul
                set /A FileCount+=1
            )
            endlocal
        ) else (
            echo/
            echo ERROR: Moving video files not possible because of file names with ! in name.
            echo/
            echo Please rename first the following files(s^) in: %%#
            echo/
            dir *!*.mp4 /A-D /B
            echo/
            pause
        )
        popd
    ) else (
        echo/
        echo ERROR: Failed to change to directory: %%#
        echo/
        pause
    )
)
endlocal

Еще одна функция, которая была бы очень полезна для меня, — выбирать файлы MP4 случайным образом каждый раз, когда я запускаю пакетный файл.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Первый пакетный файл без случайного выбора файлов MP4.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FilesInFolder=10"
set "FoldersInFolders=50"
set "MaxTotalFolders=120"

for %%# in ("%USERPROFILE%\Videos" "D:\Videos" "F:\Temp\Videos" "\\MyNAS\Videos") do call :MoveVideos %%#
goto EndBatch

:MoveVideos
pushd %1 2>nul
if errorlevel 1 (
    echo/
    echo ERROR: Failed to change to directory: %1
    echo/
    pause
    goto :EOF
)    
if exist "*!*.mp4" (
    echo/
    echo ERROR: Moving video files not possible because of file names with ! in name.
    echo/
    echo Please rename first the following files(s^) in: %1
    echo/
    dir *!*.mp4 /A-D /B
    echo/
    popd
    pause
    goto :EOF
)
setlocal EnableDelayedExpansion
set "FileCount=%FilesInFolder%"
set "CanalIndex=0"
set "FolderCount=-1"
set "VideosIndex=%FoldersInFolders%
for /F "eol=| delims = " %%I in ('dir *.mp4 /A-D /B /ON 2^>nul') do (
    if !FileCount! == %FilesInFolder% (
        set FileCount=0
        if !VideosIndex! == %FoldersInFolders% (
            set /A CanalIndex+=1
            set VideosIndex=1
        ) else set /A VideosIndex+=1
        set /A FolderCount+=1
        if !FolderCount! == %MaxTotalFolders% goto EndMove
        set "TargetFolder=Canal-!CanalIndex!\Videos-!VideosIndex!"
        md "!TargetFolder!" 2>nul
    )
    move /Y "%%I" "!TargetFolder!\" >nul
    set /A FileCount+=1
)
:EndMove
endlocal
popd
goto :EOF

:EndBatch
endlocal

Используется подпрограмма с именем MoveVideos, чтобы иметь возможность использовать goto :EOF для прекращения перемещения файлов в текущем каталоге в подкаталоги при достижении максимального общего количества папок, как определено с помощью MaxTotalFolders и подсчитано с помощью FolderCount во втором цикле FOR.

Этот пакетный файл создает с тремя значениями, определенными вверху, для каталога с файлами MP4 Video001.mp4Video1203.mp4 структуру каталогов со следующими файлами:

  • Канал-1
    • Видео-1
      • Видео0001.mp4
      • :
      • Видео0010.mp4
    • :
    • Видео-50
      • Видео0491.mp4
      • :
      • Видео0500.mp4
  • Канал-2
    • Видео-1
      • Видео0501.mp4
      • :
      • Видео0510.mp4
    • :
    • Видео-50
      • Видео0991.mp4
      • :
      • Видео1000.mp4
  • Канал-3
    • Видео-1
      • Видео1001.mp4
      • :
      • Видео1010.mp4
    • :
    • Видео-20
      • Видео1191.mp4
      • :
      • Видео1200.mp4
  • Видео1201.mp4
  • Видео1202.mp4
  • Видео1203.mp4

Этот первый пакетный файл занял 1,58 секунды для задачи перемещения файлов на моем ПК.


Второй пакетный файл со случайным выбором файлов MP4.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FilesInFolder=10"
set "FoldersInFolders=50"
set "MaxTotalFolders=120"

for %%# in ("%USERPROFILE%\Videos" "D:\Videos" "F:\Temp\Videos" "\\MyNAS\Videos") do call :MoveVideos %%#
goto EndBatch

:MoveVideos
pushd %1 2>nul
if errorlevel 1 (
    echo/
    echo ERROR: Failed to change to directory: %1
    echo/
    pause
    goto :EOF
)    
if exist "*!*.mp4" (
    echo/
    echo ERROR: Moving video files not possible because of file names with ! in name.
    echo/
    echo Please rename first the following files(s^) in: %1
    echo/
    dir *!*.mp4 /A-D /B
    echo/
    popd
    pause
    goto :EOF
)
setlocal EnableDelayedExpansion
set "FileCount=%FilesInFolder%"
set "CanalIndex=0"
set "FolderCount=-1"
set "VideosIndex=%FoldersInFolders%
set "TotalFileCount=0"
for /F "eol=| delims = " %%I in ('dir *.mp4 /A-D /B /ON 2^>nul') do set /A TotalFileCount+=1
:NextFile
if %TotalFileCount% == 0 goto EndMove
if %TotalFileCount% LEQ 32768 set /A "FileIndex=%RANDOM% %% TotalFileCount" & goto MoveFile
set /A FileGroups=TotalFileCount / 32768
set /A LastFileCount=TotalFileCount %% 32768
set "LastGroupIndex=%FileGroups%"
if not %LastFileCount% == 0 set /A FileGroups+=1
set /A GroupMultiplier=%RANDOM% %% FileGroups
if not %GroupMultiplier% == %LastGroupIndex% (set /A "FileIndex=GroupMultiplier * 32768 + %RANDOM%") else set /A "FileIndex=(FileGroups - 1) * 32768 + (%RANDOM% %% LastFileCount)"
:MoveFile
if not %FileIndex% == 0 (set "SkipValue=skip=%FileIndex% ") else set "SkipValue = "
for /F "%SkipValue%eol=| delims = " %%I in ('dir *.mp4 /A-D /B 2^>nul') do (
    if !FileCount! == %FilesInFolder% (
        set FileCount=0
        if !VideosIndex! == %FoldersInFolders% (
            set /A CanalIndex+=1
            set VideosIndex=1
        ) else set /A VideosIndex+=1
        set /A FolderCount+=1
        if !FolderCount! == %MaxTotalFolders% goto EndMove
        set "TargetFolder=Canal-!CanalIndex!\Videos-!VideosIndex!"
        md "!TargetFolder!" 2>nul
    )
    move /Y "%%I" "!TargetFolder!\" >nul
    set /A FileCount+=1
    set /A TotalFileCount-=1
    goto NextFile
)
:EndMove
endlocal
popd
goto :EOF

:EndBatch
endlocal

Этот вариант намного медленнее из-за рандомизации. На моем компьютере эта работа заняла 18,93 секунды.

Он создает то же дерево каталогов, что и первый пакетный файл в текущем каталоге, содержащий файлы MP4 от Video001.mp4 до Video1203.mp4, но какой файл перемещается в какой каталог, действительно случайный.


Вот третий вариант, также со случайным выбором следующего видеофайла для перемещения.

@echo off
echo %TIME%
setlocal EnableExtensions DisableDelayedExpansion
set "FilesInFolder=10"
set "FoldersInFolders=50"
set "MaxTotalFolders=120"
for /F "delims= = " %%I in ('set # 2^>nul') do set "%%I = "

for %%# in ("%USERPROFILE%\Videos" "D:\Videos" "F:\Temp\Videos" "\\MyNAS\Videos") do call :MoveVideos %%#
goto EndBatch

:MoveVideos
pushd %1 2>nul
if errorlevel 1 (
    echo/
    echo ERROR: Failed to change to directory: %1
    echo/
    pause
    goto :EOF
)    
if exist "*!*.mp4" (
    echo/
    echo ERROR: Moving video files not possible because of file names with ! in name.
    echo/
    echo Please rename first the following files(s^) in: %1
    echo/
    dir *!*.mp4 /A-D /B
    echo/
    popd
    pause
    goto :EOF
)
setlocal EnableDelayedExpansion
set "FileCount=%FilesInFolder%"
set "CanalIndex=0"
set "FolderCount=-1"
set "VideosIndex=%FoldersInFolders%
set "TotalFileCount=0"
for /F "eol=| delims = " %%I in ('dir *.mp4 /A-D /B /ON 2^>nul') do set "#!TotalFileCount!=%%I" & set /A TotalFileCount+=1
:NextFile
if %TotalFileCount% == 0 goto EndMove
if %TotalFileCount% LEQ 32768 set /A "FileIndex=%RANDOM% %% TotalFileCount" & goto MoveFile
set /A FileGroups=TotalFileCount / 32768
set /A LastFileCount=TotalFileCount %% 32768
set "LastGroupIndex=%FileGroups%"
if not %LastFileCount% == 0 set /A FileGroups+=1
set /A GroupMultiplier=%RANDOM% %% FileGroups
if not %GroupMultiplier% == %LastGroupIndex% (set /A "FileIndex=GroupMultiplier * 32768 + %RANDOM%") else set /A "FileIndex=(FileGroups - 1) * 32768 + (%RANDOM% %% LastFileCount)"
:MoveFile
if not %FileIndex% == 0 (set "SkipValue=skip=%FileIndex% ") else set "SkipValue = "
for /F "%SkipValue%tokens=1* delims= = " %%I in ('set #') do (
    if !FileCount! == %FilesInFolder% (
        set FileCount=0
        if !VideosIndex! == %FoldersInFolders% (
            set /A CanalIndex+=1
            set VideosIndex=1
        ) else set /A VideosIndex+=1
        set /A FolderCount+=1
        if !FolderCount! == %MaxTotalFolders% goto EndMove
        set "TargetFolder=Canal-!CanalIndex!\Videos-!VideosIndex!"
        md "!TargetFolder!" 2>nul
    )
    set "%%I = "
    move /Y "%%J" "!TargetFolder!\" >nul
    set /A FileCount+=1
    set /A TotalFileCount-=1
    goto NextFile
)
:EndMove
endlocal
popd
goto :EOF

:EndBatch
endlocal

Он определяет для каждого имени видеофайла MP4 переменную среды с именем, начинающимся с #, и числом, увеличивающимся для каждого файла, и назначает текущее имя файла переменной среды. Он обрабатывает этот список переменных среды, уменьшенный на одну переменную среды после каждого перемещения файла.

Это вызывает меньше обращений к файловой системе, чем второй пакетный файл. Но в моем тесте на моем ПК для выполнения задачи перемещения видеофайлов потребовалось 20,54 секунды.


Основная причина гораздо более длительного времени со случайным выбором файлов заключается в том, что для перемещения каждого файла необходимо запустить еще один cmd.exe в фоновом режиме, чтобы вывести новый список имен видеофайлов в текущем каталоге, захватить этот список имен файлов, пропустить все имена файлов до текущего случайного индексного номера файла и переместить случайно выбранный файл.

Было бы намного лучше, если бы список переменных среды с именами видеофайлов в текущем каталоге можно было обновить, удалив переменную среды только что перемещенного файла и проверив, существует ли еще переменная среды с текущим случайно определенным номером файла в каталоге. list, чтобы переместить этот файл и в противном случае определить новый индекс случайного номера файла так часто, как это необходимо. Но такой подход может легко привести к тому, что снова и снова случайным образом будет определяться индекс файлов, которые уже были ранее перемещены. Результатом может быть почти бесконечный цикл работы, когда количество оставшихся файлов в списке переменных среды становится маленьким. Командный процессор Windows не предназначен для такой задачи.

Рандомизация сложна в случае, если количество файлов в каталоге больше 32768, потому что %RANDOM% расширяется до случайного десятичного числа от 0 до 32767. По этой причине в код пакета добавляется каскадное рандомизированное определение номера индекса файла. файл.

Рандомизация выбора следующего видеофайла для перемещения также вызывает открытие большого количества пакетных файлов, поиск следующей строки для обработки, обработку этой строки и, возможно, чтение дополнительных строк и их обработку, запоминание текущей позиции в пакетном файле, закрытие пакетного файла. . По этой причине первый пакетный файл намного эффективнее. Более современный и мощный интерпретатор сценариев, такой как PowerShell, был бы намного лучше для этой задачи, если важным требованием является случайное перемещение видеофайлов.

Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните в нем следующие команды и полностью и внимательно прочитайте отображаемые страницы справки для каждой команды.

  • call /?
  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • md /?
  • move /?
  • pause /?
  • popd /?
  • pushd /?
  • set /?
  • setlocal /?

Другие вопросы по теме