@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 случайным образом каждый раз, когда я запускаю пакетный файл.
Первый пакетный файл без случайного выбора файлов 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.mp4
–Video1203.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 /?