Как спать в командном файле?

132

Как приостановить выполнение на некоторое время в командном файле Windows между командой и следующей?

Massimo
источник
Это должно стать каноническим? Если так, то некоторый пояснительный текст может быть уместным.
Джон Гарденье
2
«Пояснительный текст» как в?
Массимо
2
Большинство, если не все, канонические вопросы, которые я видел, включают текст, описывающий цель этого вопроса.
Джон Гарденье
Или какой-то текст, объясняющий ситуацию ... Это в основном помогает с SEO, но также помогает сформировать потенциальные ответы.
Крис С
2
SEO работает просто отлично. Первый хит для меня в поиске Google.
jbo5112

Ответы:

194

Правильный способ спать в командном файле - использовать timeoutкоманду, представленную в Windows 2000.

Чтобы подождать где-то между 29 и 30 секундами :

timeout /t 30

Тайм-аут будет прерван, если пользователь нажмет любую клавишу; однако команда также принимает необязательный параметр /nobreak, который фактически игнорирует все, что пользователь может нажать, кроме явного CTRL-C:

timeout /t 30 /nobreak

Кроме того, если вы не хотите, чтобы команда выводила на экран свой обратный отсчет, вы можете перенаправить вывод NUL:

timeout /t 30 /nobreak > NUL
Massimo
источник
6
Команда timeout не работает с Windows XP даже при установленном 2003 Resource Kit, а команда sleep не работает в Windows 7, поэтому команда ping все еще может быть полезной, если вы используете командный файл на Win7 и WinXP.
12
Тайм-аут не работает в неинтерактивных сценариях: «ОШИБКА: перенаправление ввода не поддерживается, выход из процесса немедленно». поэтому иногда использование хака с «пингом» предпочтительнее.
iMysak
14

Так как это применимо и здесь, я скопирую свой ответ с другого сайта .

Если вы хотите использовать пинг, есть лучший способ. Вы захотите пропинговать адрес, который не существует, поэтому вы можете указать время ожидания с точностью до миллисекунды. К счастью, такой адрес определен в стандарте (RFC 3330), и это так 192.0.2.x. Это не выдумка, это действительно адрес с единственной целью несуществования (это может быть непонятно, но это применимо даже в локальных сетях):

192.0.2.0/24 - Этот блок назначен как «TEST-NET» для использования в документации и примере кода. Он часто используется вместе с именами доменов example.com или example.net в документации поставщика и протокола. Адреса в этом блоке не должны появляться в общедоступном Интернете.

Чтобы спать в течение 123 миллисекунд, используйте ping 192.0.2.1 -n 1 -w 123 >nul

Mafu
источник
3
Пожалуйста, не делайте этого, даже если это немного лучше, чем пинговать реальный адрес. Pingэто просто неправильный инструмент для работы.
Массимо
1
@Massimo Скорее всего, это не то, что было задумано :) Но я все же думаю, что это хорошее решение - оно работает лучше, чем тайм-аут в некоторых сценариях (в частности, с более высоким разрешением). Кроме того, он стал довольно известным, поэтому большинство людей не будут очень удивлены (то есть смущены), когда увидят его в вашем пакетном файле.
Мафу
2
@ Массимо Хорошо! Я думаю, у нас просто разные взгляды. Если вы не возражаете, я все равно оставлю этот ответ, потому что он кажется лучше, чем пинговать localhost n раз, как это чаще всего описывается.
Мафу
7
Тайм-аут является правильным решением для операционных систем, в которых он работает. ping - единственное решение, которое работает с 5.1-6.3. Поскольку 25% систем все еще используют 5.1, тайм-аут не является «правильным способом».
Вирмвуд
3
Тайм-аут - это неправильное решение для любой операционной системы, потому что он смертельно сломан даже в Windows 10. Какая польза от команды, которая терпит неудачу только потому, что ввод перенаправлен?
Гарри Джонстон
8

Вы также можете вставить пинг в localhost. Это займет 4 секунды для завершения (по умолчанию). Некоторые считают это клуджем, но все равно работает довольно хорошо.

Команда:
ping 127.0.0.1

псаломщик
источник
6
Э-э ... вся цель этого Q / A состояла в том, чтобы точно исправить два других вопроса, которые имеют это как принятый ответ, но больше не могут быть исправлены, потому что их OP больше не существует.
Массимо
6
Хотя это будет работать, это все равно, что вбивать винт с помощью молотка. Неправильный инструмент может работать, но это все еще не так.
voretaq7
1
@MarkAllen Другими словами, Windows NT4, 95, 98, ME и старше?
Крис Мак-
5
@MarkAllen - технически вам придется беспокоиться о том, pingидет ли ваша ОС или нет . Если вы достаточно волнуетесь о '95 '98 или обо мне, то вы должны быть в равной степени обеспокоены и 6.22, который не имеет pingни одного
Марк Хендерсон
4
@MarkHenderson (мне) проще вспомнить, поддерживает ли конкретный выпуск ОС TCP / IP, чем вспомнить, содержит ли он команду, которую я раньше не слышал. Ты знаешь?
Марк Аллен,
2

Отказ от ответственности : это не «идеальное» решение, так что не пытайтесь меня бить по голове тем же, что и тем, кто рекомендует ping

По возможности используйте timeoutточно. Но, как отмечено в комментариях, это не всегда вариант (например, в неинтерактивном режиме). После этого я согласен, что ping«kludge», возможно, является следующим лучшим вариантом, поскольку он очень прост. Тем не менее, я предлагаю другой вариант ... вставлять некоторые VB Script .

Основа этого решения имеет все виды применения помимо этого. Часто VBS может делать то, что не может делать пакет, или, по крайней мере, делать это намного проще. Используя технику, проиллюстрированную здесь, вы можете смешать их (не «бесшовно», а «функционально» ...)

Вот один вкладыш, чтобы создать временный скрипт, выполнить его, а затем удалить его. Скрипт спит за вас (в этом примере 3 секунды).

echo WScript.Sleep 3000 > %temp%\sleep.vbs & cscript %temp%\sleep.vbs %sleepMs% //B & del %temp%\sleep.vbs

Вот в основном то же самое, написанное немного по-другому:

set sleepMs=3000 & set sleepVbs=%temp%\sleep.vbs & echo WScript.Sleep WScript.Arguments(0) > %sleepVbs% & cscript %sleepVbs% %sleepMs% //B & del %sleepVbs%

И вот наконец-то, вроде бы ping, у CScriptсамого есть опция тайм-аута! Таким образом, если вы введете бесконечный цикл в сценарии, вы можете позволить интерпретатору принудительно установить продолжительность. Обратите внимание, что это «занятая» операция, которая потребляет ресурсы процессора, и поэтому я не рекомендую ее использовать, когда вы можете использовать WScript.Sleepпроцедуру, но я представляю ее как концептуальную опцию для полноты картины:

set sleepSec=3 & set sleepVbs=%temp%\sleep.vbs & echo While True > %sleepVbs% & echo Wend >> %sleepVbs% & cscript %sleepVbs% //B //T:%sleepSec% & del %sleepVbs%
BuvinJ
источник
Вы знаете ... вы могли бы сделать это в powershell, я полагаю, без необходимости писать файл.
Гарри Джонстон
Да, это, вероятно, еще одно хорошее решение, хотя я считаю, что оно более обратно совместимо со старыми версиями Windows.
BuvinJ