PDA

Показать полную графическую версию : [решено] Копирование большого количества файлов по сети


finderhd
12-10-2020, 10:54
Добрый день, помогите пожалуйста с решением следующей задачки. Заранее прошу прощения, если уже были подобные вопросы, просьба кинуть ссылку или готовое решение, я искал и полностью похожей задачи не нашел.

Необходимо с одного ПК ископировать большое количество файлов (оснавная папка и подпапки) на другой ПК, находящийся в одной и той же сети (сетевой доступ между ПК есть).
Размер основной папки большой, чуть более 200Гб. Содержит большое количество подпапок и мелких файлов. Т.е. с папки C:\Distr\Files\подпапки копировать на другой ПК в C:\Distr\Files\подпапки
Копирование должно пройти быстро, в течении хотя бы 12 часов (этого будет достаточно). Но если возникнет необходимость повторного копирования, то копировать необходимо будет сделать только новые подпапки или файлы. Результат копирования, по возможности, лучше записать в лог, но без перечисления (т.к. боюсь это займет много времени и лог очень сильно вырастит), а как бы в процентном соотношении, что было скопировано всё в первом случае, и только новые файлы, во втором.

DJ Mogarych
12-10-2020, 11:26
robocopy /?

megaloman
12-10-2020, 16:12
finderhd, Совсем недавно было решено (http://forum.oszone.net/post-2935229-5.html)Xcopy /D /Q /E /H /R /C /Y "\\192.168.100.23\Test1\*.*" "Z:\Box_Arc\"Чтобы на экране отображался процесс, уберите /Q, но это слегка замедлит процесс Результат копирования, по возможности, лучше записать в лог, но без перечисления »А что Вы там хотите увидеть? @Echo Off
cls
Set "BoxIn=\\192.168.100.23\Test1"
Set "BoxOut=Z:\Box_Arc\Test1"
Set "LogFile=Z:\Box_Arc\%~nx0.log"

>>"%LogFile%" 2>>&1 (
Echo ==================================== %Date% %Time% "Start %~dpnx0"
FOR /F "usebackq delims=" %%d IN (`2^>nul Dir /B /A:D "%BoxIn%"`) DO (
Echo %Date% %Time% Begin XCopy "%BoxIn%\%%d"
Xcopy /D /Q /E /H /R /C /Y "%BoxIn%\%%d\*.*" "%BoxOut%\%%d\"
Echo %Date% %Time% End XCopy "%BoxIn%\%%d"
Echo.
)
)
pause
Exit /B
При многократном запуске батников уже скопированные файлы повторно копироваться не будут, если в источнике копирования они не были изменены.

finderhd
12-10-2020, 17:19
А что Вы там хотите увидеть? »
Чтобы убедиться, что все файлы были скопированы.

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

Например.

Запустили батник, который в определенную дату скопировал всё содержимое в каталог C:\Distr\Files\
Связано это с переездом данных с одного ПК на другой. На следующий день выяснилось, что переезда как такового осуществляться не будет и будет он неизвестно когда, а файлы уже обновились. Замечу, что имена файлов не меняются, меняется только их состав (дата, а именно признак "Изменен" обновляется каждый день).

Я так понимаю, в любом случае этот скрипт должен для таких условий подойти?

В принципе, батник будет запускаться через шедулер, по расписанию, и там можно посмотреть, сколько задача работала по времени, поэтому наверное время можно и убрать, если это нагружает работу скрипта?

Iska
12-10-2020, 19:03
Чтобы убедиться, что все файлы были скопированы. »
Тогда и писать в лог нужно все каталоги и файлы.

megaloman
12-10-2020, 19:15
Iska, Не обязательно. Можно запустить батник с xcopy несколько раз c ключом /D и, при отсутствии аварийных сообщений при работе, сообщение о том, что скопировано 0 файлов позволит убедиться, что все файлы скопированы.
Можно еще сравнить суммарный объем папок ...
А при большом количестве писать в лог все каталоги и файлы контрпродуктивно, визуально убедиться, что все файлы скопированы, нельзя.

finderhd
15-10-2020, 09:49
А при большом количестве писать в лог все каталоги и файлы контрпродуктивно, визуально убедиться, что все файлы скопированы, нельзя. »
Я уже видел работу таких скриптов, там лог настолько разрастается, что просто жуть, да и само копирование из-за этого происходит медленно.

сообщение о том, что скопировано 0 файлов позволит убедиться, что все файлы скопированы. »
Я думаю этого было бы достаточно. Т.к. потом можно просто взять и сравнить по количеству файлов и папок. Правда файлов настолько много (несколько миллионов), что стандартным способом посмотреть их количество будет сжирать оперативу влет (уже проходил через это, пришлось потом чистить память мапколлектом). Но есть другие способы увидеть количество файлов и папок, с помощью определенной утилиты, которая памяти столько не жрет, поэтому посмотреть количество там и там, в принципе не проблема. Вышеуказанный скрипт будет выводить число скопированных файлов в лог?

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

megaloman
15-10-2020, 16:28
finderhd, я Вам предоставил вариант, попробуйте хоть на каких-нибудь тестовых данных, уверен, увидите ответы на свои вопросы

Iska
16-10-2020, 07:07
…да и само копирование из-за этого происходит медленно. »
В правильно реализованных — не происходит.

finderhd
11-11-2020, 10:40
я Вам предоставил вариант, попробуйте хоть на каких-нибудь тестовых данных, уверен, увидите ответы на свои вопросы »
Проверил на тестовой папке. Батник скопировал только папки и файлы внутри них, но файлы, которые лежали в корневой исходной папке (Test1), он не скопировал. И лучше наверное все-таки убрать возможность записи в лог. А то на 2 млн файлов он там много чего напишет в лог. Эта информация лишняя, я лучше с помощью утилиты посмотрю количество файлов в исходнике и там, куда они скопировались.
И еще заметил, что если запускать батник через планировщик задач, а именно так и нужно будет (во внерабочее время) то в History не видно, что он отработал (нет записи Task Completed, только Action Started), как будто он до сих пор висит в памяти. Пришлось задачу остановить вручную через End, и тогда запись Task Completed появилась.

megaloman
11-11-2020, 13:53
finderhd, Не прошло и полгода :)
И в самом деле, в корне папки Test1 файлы не копируются - моё недомыслие. Добавил это копирование:@Echo Off
cls
Set "BoxIn=\\192.168.100.23\Test1"
Set "BoxOut=Z:\Box_Arc\Test1"
Set "LogFile=Z:\Box_Arc\%~nx0.log"

>>"%LogFile%" 2>>&1 (
Echo ==================================== %Date% %Time% "Start %~dpnx0"

Echo %Date% %Time% Begin XCopy "%BoxIn%"
Xcopy /D /Q /H /R /C /Y "%BoxIn%\*.*" "%BoxOut%\"
Echo %Date% %Time% End XCopy "%BoxIn%"
Echo.

FOR /F "usebackq delims=" %%d IN (`2^>nul Dir /B /A:D "%BoxIn%"`) DO (
Echo %Date% %Time% Begin XCopy "%BoxIn%\%%d"
Xcopy /D /Q /E /H /R /C /Y "%BoxIn%\%%d\*.*" "%BoxOut%\%%d\"
Echo %Date% %Time% End XCopy "%BoxIn%\%%d"
Echo.
)
)
pause
Exit /B
И лучше наверное все-таки убрать возможность записи в лог. »Тогда это вообще одна строка@Echo Off
cls
Set "BoxIn=\\192.168.100.23\Test1"
Set "BoxOut=Z:\Box_Arc\Test1"

Xcopy /D /Q /E /H /R /C /Y "%BoxIn%\*.*" "%BoxOut%\"
pause
Exit /B
Я бы предложил альтернативу: в лог писать только начало запуска и итог работы батника@Echo Off
cls
Set "BoxIn=\\192.168.100.23\Test1"
Set "BoxOut=Z:\Box_Arc\Test1"
Set "LogFile=Z:\Box_Arc\%~nx0.log"

>>"%LogFile%" 2>&1 (
Echo ==================================== %Date% %Time% "Start %~dpnx0"
Xcopy /D /Q /E /H /R /C /Y "%BoxIn%\*.*" "%BoxOut%\"
)
pause
Exit /B
И, наконец, до меня только дошло, что возможно Вы бездумно вставили мой код в планировщик и поэтому Вы обнаружили что если запускать батник через планировщик задач, а именно так и нужно будет (во внерабочее время) то в History не видно, что он отработал (нет записи Task Completed, только Action Started), как будто он до сих пор висит в памяти. »Если в коде присутствует Pause (а я её оставлял, чтобы посмотреть на результат исполнения в командном окне), то батник в планировщике естественно никогда не завершится, Pause требует ответа. Убейте её, или напишите
Rem Pause
Надеюсь, Ваша реакция последует несколько раньше, чем Новый Год :)

Iska
11-11-2020, 22:51
Надеюсь, Ваша реакция последует несколько раньше, чем Новый Год »
«Через две, через две зимы-ыы, через две, через две весны-ыы…» :).

finderhd
13-11-2020, 11:36
Я бы предложил альтернативу: в лог писать только начало запуска и итог работы батника »
Доброго дня. Уж извините, что так поздно отвечаю. Задача не срочная, а в перспективе, просто я готовлюсь заранее так сказать :) Ваше замечание учёл, буду стараться проверить сразу, к сожалению не всегда такая возможность есть, в виду других дел. По поводу паузы и планировщика, да, моё упущение.

Согласен с Вами, альтернатива замечательная, спасибо, проверю этот вариант в самое ближайшее время и отпишусь о результатах.

finderhd
13-11-2020, 12:04
Попробовал альтернативный способ - ничего не произошло. Если батник запускать из консоли, то ничего не происходит, но лог создается
В логе следующие записи:

File not found - *.*
0 File(s) copied

И еще вопрос - можно ли сделать так, чтобы атрибуты по дате создания каталогов, как в случае файлов (с файлами в этом плане всё нормально), сохранялись, а не отображались датой запуска батника?

megaloman
13-11-2020, 15:26
finderhd, У Вас неверно указан исходный путь. Переименуйте Ваш батник в файл с расширением .txt и приложите к сообщению.
Вот вариант с проверкой существования исходного пути.@Echo Off
Set "BoxIn=\\192.168.100.23\Test1"
Set "BoxOut=Z:\Box_Arc\Test1"
Set "LogFile=Z:\Box_Arc\%~nx0.log"

>>"%LogFile%" 2>&1 (
Echo ==================================== %Date% %Time% "Start %~dpnx0"
If Not Exist "%BoxIn%\" Echo --- InBox not found "%BoxIn%" --- OutBox= "%BoxOut%"
Xcopy /D /Q /E /H /R /C /Y "%BoxIn%\*.*" "%BoxOut%\"
)
Exit /B
==================================== 13.11.2020 15:19:50,71 "Start Z:\я20111113.bat"
Скопировано файлов: 451.
==================================== 13.11.2020 15:20:02,71 "Start Z:\я20111113.bat"
Скопировано файлов: 0.
==================================== 13.11.2020 15:31:50,66 "Start Z:\я20111113.bat"
--- InBox not found "\\192.168.100.23\Test1\ttt" --- OutBox= "Z:\Box_Arc\Test1"
Не найден файл: *.*
Скопировано файлов: 0.
При первом запуске батника в выходной папке ничего не было, скопировалась куча файлов
При втором запуске ничего не скопировалось, так как всё уже было скопировано.
В третем случае я нарочно указал неверную папку - получил сообщение как у Вас
File not found - *.*
0 File(s) copied
Так что неча на зеркало пенять :)можно ли сделать так, чтобы атрибуты по дате создания каталогов, как в случае файлов (с файлами в этом плане всё нормально), сохранялись, а не отображались датой запуска батника »
Стандартных методов не знаю. И с файлами тоже не так всё просто. При копировании файла его копия имеет дату создания копии, а дата изменения - реальная. То есть дата создания файла больше даты последнего изменения. С папками (возможно я ошибаюсь), при копировании дата создания и дата изменения будут иметь дату создания копии, а далее дата изменения - дата записи последнего файла в эту папку.

finderhd
16-11-2020, 10:42
У Вас неверно указан исходный путь. Переименуйте Ваш батник в файл с расширением »
У меня стоял символ \ в конце каталога, видимо из-за него.

Стандартных методов не знаю. И с файлами тоже не так всё просто. »
В принципе, это не критично, главное наличие самого файла.

В любом случае, теперь всё работает, спасибо!

finderhd
16-11-2020, 13:21
Заметил еще один момент. В папку назначения копируются только вложенные папки, а исходная, которая указывается в батнике (Test1) не копируется, если её не указать в назначении, это не совсем удобно, если нужно выборочное копирование.

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

Set "BoxIn=\\192.168.100.23\Test1"
Set "BoxOut=Z:\Box_Arc\Test1"

megaloman
16-11-2020, 15:11
а исходная, которая указывается в батнике (Test1) не копируется, если её не указать в назначении »Копируется. Только содержимое \\192.168.100.23\Test1 попадёт в Z:\Box_Arc, просто папка Test1 не создастся. Для выборочного (и для полного тоже) копирования вот варианты:@Echo Off
Set "FromServer=\\192.168.100.23"
Set "FromFolder=Test1\Дискета_от_книги\Chapter05"

Set "BoxOut=Z:\Box_Arc"
Set "LogFile=Z:\Box_Arc\%~nx0.log"

>>"%LogFile%" 2>>&1 (
Echo ==================================== %Date% %Time% "Start %~dpnx0"

Echo %Date% %Time% Begin XCopy "%FromServer%\%FromFolder%"
Xcopy /D /Q /H /R /C /Y "%FromServer%\%FromFolder%\*.*" "%BoxOut%\%FromFolder%\"
Echo %Date% %Time% End XCopy "%FromServer%\%FromFolder%"
Echo.

FOR /F "usebackq delims=" %%d IN (`2^>nul Dir /B /A:D "%FromServer%\%FromFolder%"`) DO (
Echo %Date% %Time% Begin XCopy "%FromServer%\%FromFolder%\%%d"
Xcopy /D /Q /E /H /R /C /Y "%FromServer%\%FromFolder%\%%d\*.*" "%BoxOut%\%FromFolder%\%%d\"
Echo %Date% %Time% End XCopy "%FromServer%\%FromFolder%\%%d"
Echo.
)
)
Exit /B
@Echo Off
Set "FromServer=\\192.168.100.23"
Set "FromFolder=Test1\Дискета_от_книги\Chapter05"

Set "BoxOut=Z:\Box_Arc"
Set "LogFile=Z:\Box_Arc\%~nx0.log"

>>"%LogFile%" 2>&1 (
Echo ==================================== %Date% %Time% "Start %~dpnx0"
If Not Exist "%FromServer%\%FromFolder%\" Echo --- InBox not found "%FromServer%\%FromFolder%" --- OutBox= "%BoxOut%"
Xcopy /D /Q /E /H /R /C /Y "%FromServer%\%FromFolder%\*.*" "%BoxOut%\%FromFolder%\"
)
Exit /B
В этих примерах исходная папка
\\192.168.100.23\Дискета_от_книги\Chapter05\
с подпапками, естественно, попадёт в
Z:\Box_Arc\Test1\Дискета_от_книги\Chapter05
Папка при отсутствии будет создана.

Можно сделать так: Set "FromServer=E:"
Set "FromFolder=Тестовые_сетевые_папки\Test1\Дискета_от_книги\Chapter05"
Получим Z:\Box_Arc\Тестовые_сетевые_папки\Test1\Дискета_от_книги\Chapter05

Можно эдак: Set "FromServer=E:\Тестовые_сетевые_папки"
Set "FromFolder=Test1\Дискета_от_книги\Chapter05"
Получим Z:\Box_Arc\Test1\Дискета_от_книги\Chapter05

А можно вообще извратиться, например, для копирования с разных серверов в одну папку с идентификацией сервера в копии Set "FromServer=\"
Set "FromFolder=192.168.100.23\Test1\Дискета_от_книги\Chapter05"
Получим Z:\Box_Arc\192.168.100.23\Test1\Дискета_от_книги\Chapter05

finderhd
26-11-2020, 11:31
megaloman,
Доброго дня. Оставил самый простой вариант, без лога, который

@Echo Off
cls
Set "BoxIn=\\192.168.100.23\Test1"
Set "BoxOut=Z:\Box_Arc\Test1"

Xcopy /D /Q /E /H /R /C /Y "%BoxIn%\*.*" "%BoxOut%\"
pause
Exit /B


Все отлично скопировалось. Но к задаче добавилось условие для некоторых других папок. Т.е. их как то выделять или добавлять отдельно в бат файл не нужно, я просто их сам укажу. Как с них по такому же сценарию скопировать файлы, но в зависимости от даты создания? Например, чтобы скопировались только файлы, созданные за последний месяц, год и т.д. в количестве дней, подскажите пожалуйста.

megaloman
26-11-2020, 15:26
finderhd, Для xcopy /D:m-d-y Копирование файлов, измененных не ранее указанной даты.
Если дата не указана, заменяются только конечные файлы,
более старые, чем исходные.
Нелёгкая задача в CMD посчитать дату, вот вариант (тупо использую отлаженную процедуру):@Echo Off
cls
Set "BoxIn=\\192.168.100.23\Test1\тра ля ля\CMD_Forum"
Set "BoxOut=Z:\Box_Arc\тра ля ля\CMD_Forum"

Set /A DeltaDay=-31
FOR /F "tokens=2 delims==." %%d in ('WMIC OS GET LOCALDATETIME /VALUE') DO SET "ToDay=%%d" &Call Set "ToDay=%%ToDay:~6,2%%.%%ToDay:~4,2%%.%%ToDay:~0,4%%"
Call :FromDate %DeltaDay% %ToDay% "DDat"

If Not Exist "%BoxIn%\" (
Echo --- InBox not found "%BoxIn%\" --- OutBox= "%BoxOut%"
) Else (
Xcopy /D:%DDat:~4,2%-%DDat:~6,2%-%DDat:~0,4% /Q /S /H /R /C /Y "%BoxIn%\*.*" "%BoxOut%\"
)
pause
Exit /B

:FromDate

rem Пересчет даты на заданное кол-во дней
rem В первом аргументе +- дни
rem Во втором аргументе дата в формате dd.mm.yyyy
rem В третем аргументе имя переменной в кавычках где получим новую дату в формате yyyymmdd

rem Заимствовано http://forum.oszone.net/thread-186889.html
rem вызов Call :FromNow %DeltaDay% %Date% "yyyymmdd"
rem результат в перемменной %yyyymmdd%

SetLocal
Set "DT=%~2"
Set yyyy=%DT:~-4%& set /a mm=100%DT:~3,2%%%100& set /a dd=100%DT:~,2%%%100
Set /A JD=%~1+dd-32075+1461*(yyyy+4800+(mm-14)/12)/4+367*(mm-2-(mm-14)/12*12)/12-3*((yyyy+4900+(mm-14)/12)/100)/4
Set /A L=JD+68569,N=4*L/146097,L=L-(146097*N+3)/4,I=4000*(L+1)/1461001
Set /A L=L-1461*I/4+31,J=80*L/2447,K=L-2447*J/80,L=J/11
Set /A J=J+2-12*L,I=100*(N-49)+I+L
Set /A yyyy=I,mm=100+J,dd=100+K
EndLocal& Set "%~3=%yyyy%%mm:~-2%%dd:~-2%"
GoTo :EofSet /A DeltaDay=-31
Здесь указываем число дней для пересчета текущей даты ("-" назад).
Наверное можно то же сделать посредством forfiles.




© OSzone.net 2001-2012