Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Копирование большого количества файлов по сети (http://forum.oszone.net/showthread.php?t=346683)

finderhd 12-10-2020 10:54 2936174

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

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

DJ Mogarych 12-10-2020 11:26 2936176

Код:

robocopy /?

megaloman 12-10-2020 16:12 2936206

finderhd, Совсем недавно было решено
Можно сделать бат-файл, а можно и из командной строки
Код:

Xcopy /D /Q /E /H /R /C /Y "\\192.168.100.23\Test1\*.*" "Z:\Box_Arc\"
Чтобы на экране отображался процесс, уберите /Q, но это слегка замедлит процесс
Цитата:

Цитата finderhd
Результат копирования, по возможности, лучше записать в лог, но без перечисления »

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

@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 2936217

Цитата:

Цитата megaloman
А что Вы там хотите увидеть? »

Чтобы убедиться, что все файлы были скопированы.

Цитата:

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

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

Например.

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

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

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

Iska 12-10-2020 19:03 2936229

Цитата:

Цитата finderhd
Чтобы убедиться, что все файлы были скопированы. »

Тогда и писать в лог нужно все каталоги и файлы.

megaloman 12-10-2020 19:15 2936231

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

finderhd 15-10-2020 09:49 2936527

Цитата:

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

Я уже видел работу таких скриптов, там лог настолько разрастается, что просто жуть, да и само копирование из-за этого происходит медленно.

Цитата:

Цитата megaloman
сообщение о том, что скопировано 0 файлов позволит убедиться, что все файлы скопированы. »

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

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

megaloman 15-10-2020 16:28 2936566

finderhd, я Вам предоставил вариант, попробуйте хоть на каких-нибудь тестовых данных, уверен, увидите ответы на свои вопросы

Iska 16-10-2020 07:07 2936642

Цитата:

Цитата finderhd
…да и само копирование из-за этого происходит медленно. »

В правильно реализованных — не происходит.

finderhd 11-11-2020 10:40 2939508

Цитата:

Цитата megaloman
я Вам предоставил вариант, попробуйте хоть на каких-нибудь тестовых данных, уверен, увидите ответы на свои вопросы »

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

megaloman 11-11-2020 13:53 2939525

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

Цитата:

Цитата finderhd
И лучше наверное все-таки убрать возможность записи в лог. »

Тогда это вообще одна строка
Код:

@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

И, наконец, до меня только дошло, что возможно Вы бездумно вставили мой код в планировщик и поэтому Вы обнаружили
Цитата:

Цитата finderhd
что если запускать батник через планировщик задач, а именно так и нужно будет (во внерабочее время) то в History не видно, что он отработал (нет записи Task Completed, только Action Started), как будто он до сих пор висит в памяти. »

Если в коде присутствует Pause (а я её оставлял, чтобы посмотреть на результат исполнения в командном окне), то батник в планировщике естественно никогда не завершится, Pause требует ответа. Убейте её, или напишите
Rem Pause

Надеюсь, Ваша реакция последует несколько раньше, чем Новый Год :)

Iska 11-11-2020 22:51 2939601

Цитата:

Цитата megaloman
Надеюсь, Ваша реакция последует несколько раньше, чем Новый Год »

«Через две, через две зимы-ыы, через две, через две весны-ыы…» :).

finderhd 13-11-2020 11:36 2939810

Цитата:

Цитата megaloman
Я бы предложил альтернативу: в лог писать только начало запуска и итог работы батника »

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

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

finderhd 13-11-2020 12:04 2939813

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

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

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

megaloman 13-11-2020 15:26 2939837

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

Вот пример моего Log-файла
Цитата:

==================================== 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
можно ли сделать так, чтобы атрибуты по дате создания каталогов, как в случае файлов (с файлами в этом плане всё нормально), сохранялись, а не отображались датой запуска батника »

Стандартных методов не знаю. И с файлами тоже не так всё просто. При копировании файла его копия имеет дату создания копии, а дата изменения - реальная. То есть дата создания файла больше даты последнего изменения. С папками (возможно я ошибаюсь), при копировании дата создания и дата изменения будут иметь дату создания копии, а далее дата изменения - дата записи последнего файла в эту папку.

finderhd 16-11-2020 10:42 2940118

Цитата:

Цитата megaloman
У Вас неверно указан исходный путь. Переименуйте Ваш батник в файл с расширением »

У меня стоял символ \ в конце каталога, видимо из-за него.

Цитата:

Цитата megaloman
Стандартных методов не знаю. И с файлами тоже не так всё просто. »

В принципе, это не критично, главное наличие самого файла.

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

finderhd 16-11-2020 13:21 2940136

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

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

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

megaloman 16-11-2020 15:11 2940146

Цитата:

Цитата finderhd
а исходная, которая указывается в батнике (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 2941069

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 2941092

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 :Eof

Set /A DeltaDay=-31
Здесь указываем число дней для пересчета текущей даты ("-" назад).
Наверное можно то же сделать посредством forfiles.


Время: 19:24.

Время: 19:24.
© OSzone.net 2001-