Быстрые методы для копирования (перемещения) файлов в пакетном файле

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

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

Поэтому я написал следующий код для группировки файлов путем перемещения определенного количества файлов (показано как %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

Комментарии

  1. я использовал set /a отрегулировать %limit% которые отключены из-за findstr /n /v
  2. Этот скрипт будет скомпилирован в файл.bat и помещен в папку, содержащую файлы для сортировки.

Пример среды (свернутый):

В родительской папке 1500 документов с подпапками с именами 0,2 и 4. Сценарий будет помещен в родительскую папку и будет выполнен.


Требования к сценарию:

  1. Создать нумерованный каталог, начиная с 0, только если каталог не существует
  2. Переместите 700 файлов во вновь созданный каталог. Файлы будут перемещены, даже если количество файлов меньше 700.
  3. Повторяйте задачи 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 findstrs - первый для исключения расширений, второй для нумерации строк. Попытка использовать один findstr будет нумерация в соответствии с положением в dir команда, поэтому исключенным файлам будет присвоен номер, но они не будут переданы; следовательно, переселение будет не хватать limit

Обратите внимание, что поскольку файлы на самом деле не являются moveбуду с echo(move на месте, тот же список файлов будет повторяться снова и снова. Когда move вызванные файлы, очевидно, не будут найдены в следующей итерации]

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