Разделите длинные команды на несколько строк с помощью командного файла Windows

Как я могу разделить длинные команды на несколько строк в пакетном файле?


person Community    schedule 16.09.2008    source источник


Ответы (7)


Вы можете разбить длинные строки с помощью символа вставки ^, если помните, что символ вставки и новая строка, следующие за ним, полностью удалены. Итак, если должен быть пробел, где вы разрываете линию, добавьте пробел. (Подробнее об этом ниже.)

Пример:

copy file1.txt file2.txt

будет записано как:

copy file1.txt^
 file2.txt
person Wayne    schedule 16.09.2008
comment
Вы можете начать следующую строку без пробела, если вы добавите пробел непосредственно перед ^ и после текста команды. - person Joseph Daigle; 16.09.2008
comment
Кажется, ограничивается только первыми двумя дополнительными строками? - person Seba Illingworth; 31.07.2010
comment
У меня прекрасно работал с SQL-скриптом, который выполняет длинные SQL-запросы с использованием sqlcmd.exe. Отложенное расширение даже позволяет мне избежать символов «больше» и «меньше». Спасибо! - person djangofan; 14.11.2011
comment
@SebaIllingworth - Нет, вы всегда можете добавить [SPACE] + [^] и две пустые строки, чтобы создать в общей сложности 2 перевода строки, когда он echoed. - person James K; 19.09.2012
comment
@ Андрей М - я тебя слышу. Я не верю, что должен быть пробел до или после последнего пряника в строке, если вы пытаетесь продолжить строку. В частности, я считаю, что вы должны сделать это одним из двух способов: 1) пробел перед морковкой и в следующей строке не должно быть пробела ИЛИ 2) без пробела до или после моркови, но следующая строка начинается с пробела. - person djangofan; 10.06.2013
comment
В целях безопасности всегда заканчиваться пустой строкой при использовании вставки см. Простое каратов в пакетном файле потребляет вся память - person matt wilkie; 09.10.2013
comment
Описание пробелов вокруг каретки в этом ответе действительно запутано. Это очень просто: в результате курсор и следующая за ним новая строка не существуют. Поэтому, если там должен был быть пробел (как между параметрами команды), вам нужно поставить там пробел. Я переписал этот ответ здесь. Обычно я просто редактировал ответ, но казалось неправильным полностью переписывать чей-то ответ. - person T.J. Crowder; 08.01.2014
comment
@GavinMiller: каретка ^ после копирования и file1.txt в новой строке не будет работать Это неправда. Строку можно разделить где угодно, в том числе в середине слова, например co^␍py ^␍file1 ^␍file2. Я предлагаю вам удалить свой комментарий, чтобы избежать путаницы, тем более, что этот квест очень популярен - person Borodin; 08.08.2015
comment
@SebaIllingworth - Я попытался использовать ^, чтобы разбить свою длинную команду на 7 строк, и она работала нормально (Windows 7). Ниже приведен ответ, в котором говорится, что существует ограничение на общую длину неработающей команды - может быть, это была ваша точка доступа? Вы можете проводить тесты с короткими общими командами, такими как 'type', чтобы показать несколько файлов, таких как 1.txt, 2.txt и т. Д. - person Jaiden Snow; 24.04.2016
comment
Одна из проблем заключается в том, что ^ должен быть последним символом в строке, то есть без пробелов после. У меня были проблемы с этим, и оказалось, что после каретки у меня было много пробелов, которые не были легко заметны в редакторе, который я использовал. - person GregHNZ; 09.08.2017
comment
Убедитесь, что ваша переменная не заключена в двойные кавычки, для ее работы требуется дополнительное волшебство: stackoverflow.com/questions/4643376/ - person Noumenon; 13.05.2018
comment
Специальный символ <>|"&^ в начале обернутого фрагмента потеряет свое особое значение из-за его экранирования с помощью символа продолжения. Так что начинать каждый завернутый кусок с пробела кажется безопасной привычкой. the line continuation escapes the first character of the next line - @ dbenham, апрель 2012 г. - person eel ghEEz; 06.03.2019

Правило для каретки:

Каретка в конце строки добавляет следующую строку, первый символ добавленной строки будет экранирован.

Вы можете использовать курсор несколько раз, но полная строка не должна превышать максимальную длину строки ~ 8192 символа (Windows XP, Windows Vista и Windows 7).

echo Test1
echo one ^
two ^
three ^
four^
*
--- Output ---
Test1
one two three four*

echo Test2
echo one & echo two
--- Output ---
Test2
one
two

echo Test3
echo one & ^
echo two
--- Output ---
Test3
one
two

echo Test4
echo one ^
& echo two
--- Output ---
Test4
one & echo two

Чтобы подавить экранирование следующего символа, вы можете использовать перенаправление.

Перенаправление должно быть непосредственно перед курсором. Но есть одно любопытство с перенаправлением перед кареткой.

Если вы поместите маркер на каретку, маркер будет удален.

echo Test5
echo one <nul ^
& echo two
--- Output ---
Test5
one
two


echo Test6
echo one <nul ThisTokenIsLost^
& echo two
--- Output ---
Test6
one
two

Кроме того, в строку можно встроить перевод строки:

setlocal EnableDelayedExpansion
set text=This creates ^

a line feed
echo Test7: %text%
echo Test8: !text!
--- Output ---
Test7: This creates
Test8: This creates
a line feed

Пустая строка важна для успеха. Это работает только с отложенным расширением, иначе остальная часть строки игнорируется после перевода строки.

Это работает, потому что курсор в конце строки игнорирует следующий перевод строки и экранирует следующий символ, даже если следующий символ также является переводом строки (на этом этапе возврат каретки всегда игнорируется).

person jeb    schedule 15.12.2010
comment
Последний блок кода с примером перевода строки не отображает пустую строку, даже если она есть. (По крайней мере, это не отображается в IE7) Попробуйте переформатировать вместо этого, используя цитату. - person dbenham; 23.11.2011
comment
Вопрос в том, должны ли мы поддерживать плохой инструмент, который не следует правилам (кто-то называет его браузером, но это не так), или вам следует переключиться на браузер? - person jeb; 24.11.2011
comment
у меня были двойные кавычки, окружающие мои значения, как в set var = text здесь ^, но это не работает. Удалите двойные кавычки, и все в порядке. - person rjt; 05.04.2016
comment
@jeb написал пример неудачного сценария cmd, но затем нашел этот вопрос: stackoverflow.com/questions/4643376/ - person rjt; 06.04.2016
comment
Это не работает, если следующая строка начинается с кавычки: copy ^[newline]"file1.txt" ^[newline]"file2.txt" не работает! Пришлось добавить пробел: copy ^[newline] "file1.txt" ^[newline] "file2.txt". - person Alexander Gelbukh; 07.05.2020
comment
@AlexanderGelbukh Это ожидаемое поведение, описанное ...the first character of the appended line will be escaped., вы можете использовать пробел или решение, описанное в To suppress the escaping of the next character you can use a redirection. ... - person jeb; 07.10.2020

(Это в основном перезапись ответа Уэйна, но с устранением путаницы вокруг каретки. Итак, я опубликовал его как CW. Я не стесняюсь редактировать ответы, но полностью их переписывать кажется неуместным.)

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

Примеры: (все протестированы в Windows XP и Windows 7)

xcopy file1.txt file2.txt

можно записать как:

xcopy^
 file1.txt^
 file2.txt

or

xcopy ^
file1.txt ^
file2.txt

или даже

xc^
opy ^
file1.txt ^
file2.txt

(Последний вариант работает, потому что нет пробелов между xc и ^, и нет пробелов в начале следующей строки. Поэтому, когда вы удаляете ^ и новую строку, вы получаете ..._ 10_.)

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

Убедитесь, что ^ не последнее место в пакетном файле, так как там кажется серьезной проблемой.

person Community    schedule 08.01.2014

Несколько команд можно заключить в круглые скобки и распределить по многочисленным строкам; так что что-то вроде echo hi && echo hello можно написать так:

( echo hi
  echo hello )

Также могут помочь переменные:

set AFILEPATH="C:\SOME\LONG\PATH\TO\A\FILE"
if exist %AFILEPATH% (
  start "" /b %AFILEPATH% -option C:\PATH\TO\SETTING...
) else (
...

Также я заметил с помощью вставок (^), что условным операторам if нравится, что они следуют только в том случае, если присутствует пробел:

if exist ^
person Todd Partridge    schedule 12.02.2016
comment
Строка cmd1.bat && cmd2.bat отличается от формы скобок: выполнить cmd2.bat, если cmd1.bat выполнено успешно (-без установки %errorcode%). Последняя форма выполняется безоговорочно. Несколько неожиданным (по крайней мере для меня) является то, что, очевидно, вы не можете использовать комбинацию обоих +, т.е. добавить && перед разрывом строки. - person Paul Michalik; 19.07.2018
comment
( echo <line break here> hello ) приводит к пустой строке. - person basickarl; 13.02.2020
comment
лучший и самый чистый ответ! каретки уродливы и проблематичны в регулярном выражении - person neoscribe; 19.05.2020

Однако кажется, что разделение в середине значений цикла for не требует каретки (и на самом деле попытка использовать ее будет считаться синтаксической ошибкой). Например,

for %n in (hello
bye) do echo %n

Обратите внимание, что даже после приветствия или перед «до свидания» места не требуется.

person Mohammed Safwat    schedule 24.08.2014
comment
Конечно, это часть синтаксиса for: разделителями элементов в for-set являются пробел, запятая, точка с запятой, знак равенства, символ TAB и новые строки. - person Aacini; 11.02.2016
comment
Но что, если do часть содержит несколько / вложенных if-else операторов? - person Vicky Dev; 19.12.2016
comment
Затем вы можете просто использовать круглые скобки, чтобы заключить такие операторы, как% n, в (привет, пока) do (echo% n echo% n) - person Mohammed Safwat; 28.12.2016
comment
это возможный подход, но сначала вам нужно сохранить все элементы в одной строке и выполнить его один раз. - person npocmaka; 09.11.2020

Хотя carret будет предпочтительным способом сделать это, вот еще один подход с использованием макроса, который создает команду из переданных аргументов:

@echo off
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
set "{{=setlocal enableDelayedExpansion&for %%a in (" & set "}}="::end::" ) do if "%%~a" neq "::end::" (set command=!command! %%a) else (call !command! & endlocal)"
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

%{{%
    echo
    "command"
    written
    on a
    few lines
%}}%

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

person npocmaka    schedule 09.11.2020

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

myprog "needs this to be quoted"

можно записать как:

myprog ^"needs this ^
to be quoted^"

но остерегайтесь начинать строку с каретки после завершения строки с кареткой - потому что она будет отображаться как каретка ..?:

echo ^"^
needs this ^
to be quoted^
^"

- ›необходимо процитировать ^

person Simon H    schedule 21.07.2021
comment
Вам не нужно экранировать последнюю цитату. Каретка (или любой другой специальный символ) в первом столбце новой строки будет экранирована многострочной вставкой - person jeb; 21.07.2021
comment
хорошая точка зрения! :) ... Я использую это для разделения ОЧЕНЬ длинных аргументов ffmpeg '-vf', и это работает. - person Simon H; 22.07.2021