Показать полную графическую версию : Параллельное копирование файлов в bat.
Привет всем.
Такой вопрос возник.
Есть два диапазона значений, постоянно вырастающих на единицу.
Одно лежит в одном диапазоне (допустим 1-10), другое (15-25).
Нужно создавать папки именованные значением переменной диапазона.
Т.е. папки 1\ 2\ 3\ 4\ 5\ 6\ и т.д.
В эти папки нужно копировать один и тот-же файл.
Нужно написать такой батник, чтобы копирование происходило параллельно.
Т.е. одновременно идёт создание папки допустим 1 и папки 15.
Проблема в том, что у меня постоянно выходит последовательное копирование при помощи for.
Код набросал, но так и не додумался как сделать параллельное копирование.
+ перед каждым копированием, нужно пинговать удаленный сервер (на самом деле 1,2,3 это цифры в IP, но не суть).
Dremor, Ваши интервалы различны по длине: в одном 10 значений, в другом — 11.
Нужно написать такой батник, чтобы копирование происходило параллельно.
Т.е. одновременно идёт создание папки допустим 1 и папки 15. »
Почему не «1», «2», «3», … «10», «15», «16», …«25» одновременно?
(на самом деле 1,2,3 это цифры в IP, но не суть). »
Как раз таки суть. Рассказывайте подробно.
Нужно написать такой батник, чтобы копирование происходило параллельно »
В общих чертах: запускать из батника не просто "COPY", а "start cmd /c COPY" (то же -- с MD). Тогда переход к следующей команде исходного батника будет происходить не дожидаясь завершения текущей команды.
Да и слово "параллельно"... Вопрос, что быстрее происходит: исполнение команды -- или синтаксический разбор системой батника и переход к следующей строке.
@echo off
for /L %%i in (11,1,34) do call:pingtest %%i && if %errorlevel%==0 call:copyoper %%i
exit /b 0
setlocal
:pingtest
1>nul 2>&1 ping -n 1 -w 200 192.168.%1.1 && (echo 192.168.%1.1 = OK) || echo No connection with 192.168.%1.1 at %TIME% %DATE% && echo No connection with 192.168.%1.1 at %TIME% %DATE% >> errolog.txt
exit /b
endlocal
setlocal
:copyoper
1>nul 2>&1 md testf\192.168.%1.1 && 1>nul 2>&1 copy %COMPUTERNAME%.txt testf\192.168.%1.1
if %errorlevel%==0 echo File succesfully copied to 192.168.%1.1
endlocal
Вот пример кода батника copy1.bat, который вызывается run.bat
Как можно это реализовать при помощи "start cmd /c COPY" в цикле?
Как раз таки суть. Рассказывайте подробно.
Один и тот-же файл копируется на 192.168.%%i.1. где %%i += 1
Это я реализовал, но последовательно.
Foreigner
12-01-2014, 15:28
Попробуй так:
@echo off
setlocal
for /l %%i in (11,1,34) do start /b cmd /c "ping -n 1 192.168.%%i.1 && ( xcopy %computername%.txt testfld\192.168.%%i.1\ )"
Спасибо, а как теперь организовать параллельную запись?
Т.е. два цикла, один этот (11,1,34), другой (36,1,79)?
Я просто не могу понять, как запустить два цикла параллельно.
Ладно если бы цикл в цикле был, но здесь в теле цикла реализовать это очень трудно.
Я то сделал два батника, copy1.bat и copy2.bat, они одинаковые, просто работают с двумя диапазонами.
Foreigner
12-01-2014, 16:18
Dremor, Просто прописать в run.cmd
start copy.cmd 11 34
start copy.cmd 36 79
А в copy.cmd:
for /l %%i in (%1,1,%2) do ....
Т.е. получится, что запускается 2 копии copy.cmd c разными аргументами
И лучше copy.cmd назвать как-нибудь иначе, на всякий случай.
Спасибо, сегодня попробую обязательно.
Подскажите ещё пожалуйста, как послать вывод c copy.cmd на главное окно?
Т.е. я запустил run.bat, пошла copy.cmd и чтобы все ошибки она выводила в run.bat?
Главное, чтобы размеры копируемого по сети были адекватными. Иначе параллелизация приведёт к противоположному от ожидаемого эффекту.
В общем попробывал все и все-равно возникают проблемы.
Нужно чтобы при отсутствии пинга выводилось сообщение об ошибке, а если связи нет, то и не должно быть копирования.
Для этого мне нужно объеденить проверку пинга в одну функцию, но этого не сделать.
В итоге сделал так, нормально не работает
test.cmd
@echo off
set fvar=%3
for /l %%i in (%1,1,%2) do (
(1>nul 2>&1 ping -n 1 192.168.%%i.1) && echo No connection to 192.168.%%i.1 || echo Con to 192.168.%%i.1 && (md test\192.168.%%i.1 && copy %fvar% test\192.168.%%i.1) || echo Cannot copy %fvar%
run.bat
@echo off
set filename="%COMPUTERNAME%.txt"
call make.bat %filename% && if %errorlevel%==0 (
start test.cmd 11 34 %filename%
start test.cmd 42 80 %filename%
)
pause
Помогите пожалуйста сделать так, чтобы создание папки и копирование происходили только тогда, когда пинг есть, при этом если его нету, должно выводиться свое сообщение что связи нет.
Foreigner
12-01-2014, 19:25
Dremor, У меня такой вариант работает:
@echo off
setlocal
set "exec=xcopy %computername%.txt D:\Downloads\%%%i.ru\"
set "error=echo wrong host %%%i.ru"
for %%i in (ya,щщ,юю) do start /b cmd /c "1>nul 2>&1 ping -n 1 %%i.ru && (%exec%) || (%error%)
У меня нет возможности пинговать устройства в локалке, поэтому взял существующий ya.ru и два заведомо ложных, в вашем случае измените на:
@echo off
setlocal
set "exec=xcopy %computername%.txt testfolder\192.168.%%%i.1\"
set "error=echo wrong ip 192.168.%%%i.1"
for /l %%i in (%1,1,%2) do start /b cmd /c "1>nul 2>&1 ping -n 1 192.168.%%i.1 && (%exec%) || (%error%)
PS. Для проверки пинга будет лучше и правильней такая конструкция:
... ping -n 1 192.168.%%i.1 | 1>nul findstr "TTL" && ( %exec% ) || ( %error% )
Исправил проверку пинга и вроде заработало, пока ещё решаю остальные вопросы :)
Ложная тревога, теперь с такой проверкой пинга в любом случае выдаёт ошибку wrong ip, хотя пингую локальный 192.168.1.1
:(
В случае же отсутствия строчки | 1>nul findstr "TTL" не выдается сообщение об ошибке пинга.
Файлы тоже копируются.
Хотя проверил сам, все айпишники не пингуются.
Разберусь - отпишусь, похоже ковычки где-то пропустил.
Теперь возникла еще проблема:
Мы количество отчетов об ошибках урезали, а нужно чтобы выдавались также ошибки о том, что файл не может быть копирован.
Т.е. на пинг проверили, а потом ещё на само копирование.
Да, ещё непонятно как вывести сообщения об ошибках в главное окно.
Или сделать так, чтобы работало только одно окно. (Встаёт проблема параллельности копирования)
Foreigner
12-01-2014, 20:40
Dremor, Если не секрет, зачем эта параллельность? Просто возникают затруднения в написании, а выигрыш во времени скорее всего сомнительный. Убрать все эти start cmd и ничего не потеряешь. Файлы текстовые, так ведь, если тяжелые, то хотя бы запускать только xcopy.exe в нескольких экземплярах:
@echo off
setlocal
for /l %%i in (%1,1,%2) do (
ping -n 1 192.168.%%i.1 | 1>nul findstr "TTL" && (
start /b 1>nul 2>&1 xcopy %computername%.txt "folder\192.168.%%i.1\" || echo can't copy to folder\192.168.%%i.1
) || (
echo ping error 192.168.%%i.1
))
Это мне так задали сделать, зачем я сам не понимаю.
Последовательно я давно все написал.
Вообще мне легче это всё в С++ сделать, чем париться с гениальной cmd, но надо значит надо :)
Спасибо за пример, я также сделал.
От этих скобочек уже голова болит.
Я уже по сути все сделал, осталось последнее условие.
Как сделать вывод в run.bat, когда start.cmd Отработали?
Т.е. операция прошла и мне нужно сделать вывод о том, что батник работу завершил и какой результат (ну тут понятно, еррорлевел наверное проще сделать).
Foreigner
12-01-2014, 21:00
Как сделать вывод в run.bat, когда start.cmd Отработали? »
Боюсь, что он ничего не знает о запущенных батниках, он просто запускает и прекращает свою работу. Можно конечно добавить waitfor:
:: run.cmd
@echo off
start 1.cmd
waitfor signal_name
:: 1.cmd
timeout 5
waitfor /si signal_name
Ох уж эти батники, я за день общения с ними (до этого вообще 0 знал по ним) свихнулся просто напросто.
Лучше бы был встроенный компилятор многих языков, написал код и всё.
Спасибо за помощь Foreigner, очень помог.
И лучше copy.cmd назвать как-нибудь иначе, на всякий случай. »
"Эт точно!" Стандартная ошибка -- назвать .bat/.cmd именем существующей команды, а затем удивляться, почему всё работает не так как должно работать, если запускать (или изнутри другой программы передавать параметры) без явного указания расширения. :)
Dremor,
Да и run.bat лучше бы переобозвать (поскольку имя программ run.exe, как и launch.exe, тоже периодически попадается, и обработка может уйти к таким программам).
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.