Быстрые методы для копирования (перемещения) файлов в пакетном файле
У меня есть огромное количество файлов в одном каталоге, которые мне нужно проверить.
Проблема была в том, что проводнику файлов требуется слишком много времени для загрузки списка файлов, и весь мой компьютер работает медленно.
Поэтому я написал следующий код для группировки файлов путем перемещения определенного количества файлов (показано как %limit%
и будет 700) для нумерованных папок (показано как %DirN%
)
for /f "tokens=1-2 delims=:" %%a in ('dir /b /a-d ^|findstr /n /v ".bat .cmd .txt"') do if %%a lss %limit% robocopy "%cd%" "%cd%\%DirN%" "%%b" /mov >nul
Этот код сам по себе работал нормально так же, как он был спроектирован, но была обнаружена дополнительная проблема: скорость.
Так как я имею дело с файлами, которые занимают 20 ГБ моего диска, то для перемещения файлов таким способом, кажется, требуется вечность.
Есть ли более быстрый способ копирования (перемещения) файлов?
пс. я пробовал /move
а также /xcopy
команды, но не видел много различий.
Поскольку был запрос на контекст, я прилагаю полный код:
@echo off
pushd %~dp0
set DirN=-1
:Check_DirN
set LeftOver=
for /f "tokens=*" %%a in ('dir /b /a-d ^|findstr /v ".bat .cmd .txt"') do (set LeftOver=%%a)
if "%LeftOver%"=="" goto Done
set /a DirN+=1
if exist "%cd%\%DirN%" goto Check_DirN
:Create
md %DirN%
:Move
cls
echo Moving files to Directory %DirN%...
set /a limit=700+2
for /f "tokens=1-2 delims=:" %%a in ('dir /b /a-d ^|findstr /n /v ".bat .cmd .txt"') do if %%a lss %limit% robocopy "%cd%" "%cd%\%DirN%" "%%b" /mov >nul
goto Check_DirN
exit
:Done
del list.txt>nul 2>&1
echo Task Done!
pause>nul
Комментарии
- я использовал
set /a
отрегулировать%limit%
которые отключены из-заfindstr /n /v
- Этот скрипт будет скомпилирован в файл.bat и помещен в папку, содержащую файлы для сортировки.
Пример среды (свернутый):
В родительской папке 1500 документов с подпапками с именами 0,2 и 4. Сценарий будет помещен в родительскую папку и будет выполнен.
Требования к сценарию:
- Создать нумерованный каталог, начиная с 0, только если каталог не существует
- Переместите 700 файлов во вновь созданный каталог. Файлы будут перемещены, даже если количество файлов меньше 700.
- Повторяйте задачи 1 и 2, пока в родительском каталоге не останется файлов.
Пример результата выполнения скрипта:
В родительской папке есть подпапки с именами 0, 1, 2, 3, 4 и 5 со сценарием. В подпапках 1 и 3 будет по 700 документов. В подпапках 5 будет 100 документов. В подпапках 0, 2 и 4 изменений не будет.
2 ответа
Я предоставляю это как альтернативу ответу Магу. Я использовал ваш начальный RoboCopy
команда и поскольку это внешняя команда, удалили зависимость от внешней FindStr
надеюсь, принять во внимание любую разницу в скорости.
@Echo Off
If /I Not "%__CD__%"=="%~dp0" PushD "%~dp0" 2>Nul||Exit/B
SetLocal EnableDelayedExpansion
Set "DirN=-1"
:Check_DirN
Set/A "DirN+=1"
If Exist "%DirN%" GoTo Check_DirN
Set "limit=700"
For %%A In (*.bat *.cmd *.txt) Do (
If Not Exist "%DirN%" MD "%DirN%"
If /I Not "%%~nxA"=="%~nx0" RoboCopy . "%DirN%" "%%A" /MOV 1>NUL
Set/A "limit-=1"
If !limit! Lss 0 GoTo Check_DirN
)
Echo(Task Done!
Timeout -1 1>Nul
@echo off
pushd %~dp0
set DirN=-1
:Check_DirN
set /a DirN+=1
if exist "%cd%\%DirN%" goto Check_DirN
md %DirN%
set /a limit=700
for /f "tokens=1* delims=:" %%a in ('dir /b /a-d ^|findstr /v ".bat .cmd .txt" ^|findstr /n "." ') do (
if %%a gtr %limit% goto Check_DirN
set /a limit=0
echo(move "%%b" "%cd%\%DirN%\"
)
if %limit% neq 0 rd %DirN%
echo Task Done!
pause>nul
Требуемые команды MOVE просто ECHO
Эд для тестирования. После проверки правильности команд измените ECHO(MOVE
в MOVE
на самом деле переместить файлы. присоединять >nul
подавить сообщения отчета (например, 1 file moved
)
Сначала создайте новый каталог. Нет необходимости привлекать for
в этом.
Затем установите свой лимит, затем выберите и пронумеруйте свой список каталогов и переместите каждый файл по очереди к месту назначения.
Когда лимит файлов достигнут, вернитесь назад и создайте новый каталог назначения.
Обратите внимание, что delayedexpansion
эксплуатируется. %limit%
будет заменен его значением на этапе анализа и будет установлен в 0, если какой-либо файл будет перемещен. Поскольку замена его реального значения уже была выполнена синтаксическим анализатором, это не повлияет на цикл, но может быть обнаружено после того, как цикл завершен, что означает "файл был перемещен".
Если файл не был перемещен, то limit
останется ненулевым при выходе for
цикл, следовательно, вновь созданный каталог пуст и может быть удален.
Я бы посоветовал вам попробовать это с меньшим ограничением для фиктивного каталога, чтобы убедиться, что он работает. Должно быть существенно быстрее.
[edit - создать каталог после проверки, что он еще не существует]
[edit2- каскад 2 findstr
s - первый для исключения расширений, второй для нумерации строк. Попытка использовать один findstr
будет нумерация в соответствии с положением в dir
команда, поэтому исключенным файлам будет присвоен номер, но они не будут переданы; следовательно, переселение будет не хватать limit
Обратите внимание, что поскольку файлы на самом деле не являются move
буду с echo(move
на месте, тот же список файлов будет повторяться снова и снова. Когда move
вызванные файлы, очевидно, не будут найдены в следующей итерации]