1 (изменено: Rumata, 2015-12-28 10:16:56)

Тема: CMD/BAT: Хитрости и нелепости интерпретатора

Решил собрать известные хитрости и (возможные) нелепости

* * *

Команда echo - самый безопасный и надежный вызов с использованием символа двоеточие:


echo:%VAR%

* * *

Эмуляция массивов


@echo off

setlocal enabledelayedexpansion

:: инициализировать 10 переменные вида arr.X случайными числами
for /l %%i in ( 0, 1, 9 ) do (
    set /a arr.%%i=!RANDOM!
)

set arr

endlocal

* * *

Некоторые спец. и управляющие символы


:: Backspace
for /f %%A in ('"prompt $H&for %%B in (1) do rem"') do set "BS=%%A"

:: ESC
for /f %%A in ('"prompt $E&for %%B in (1) do rem"') do set "ESC=%%A"
set "ESC=%ESC:~0,1%"

:: CR
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

:: LF
set LF=^


rem Две пустые строки выше обязательны!!!

* * *

Макросы для установки кода возврата 0 или 1 (без вызова подпрограммы)


::
:: macro.true
::
:: Returns the status (0)
::
:: Example
::     %macro.true%
::
set macro.true=( call )

::
:: macro.false
::
:: Returns the status (1)
::
:: Example
::     %macro.false%
::
set macro.false=(call)

* * *

Параметризованный вызов макросов (подробнее в теме CMD/BAT: Пакетные макросы с параметрами)


::
:: macro.call
::
:: Calls macro with parameters
::
:: Example
::     set macro.example=do ( echo %%a&echo %%b&echo %%c)
::     %macro.call% ( "arg1 arg2 arg3" ) %macro.example%
set macro.call=for /f "tokens=1-26" %%a in
( 2 * b ) || ! ( 2 * b )

2

Re: CMD/BAT: Хитрости и нелепости интерпретатора

http://www.dostips.com/forum/viewtopic. … 071#p32071
Очень интересный способ конвертации целых чисел в шестнадцатеричное представление


cmd /c exit /b 3735928559
echo %=ExitCode%
( 2 * b ) || ! ( 2 * b )

3

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata пишет:

Очень интересный способ конвертации целых чисел в шестнадцатеричное представление.

Есди код не защищен авторским правом, то я непрочь переписать hex2dec заново на чистом cmd. http://forum.vingrad.ru/html/emoticons/pack/girl_crazy.gif

4

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Есди код не защищен авторским правом

Не знаю, это не ко мне. Можно спросить автора скрипта, пройдя по ссылке.

А вот это уже нелепость - пробелы влияют на результат:


for /f %A in ('"prompt $E&for %B in (1) do rem"') do @echo:%A
for /f %A in ('"prompt $E &for %B in (1) do rem"') do @echo:%A
( 2 * b ) || ! ( 2 * b )

5

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata пишет:

А вот это уже нелепость - пробелы влияют на результат…

Вопрос немного спорный, но я не вижу большой нелепости в возможности использовать в команде PROMPT пробелы в непосредственном виде, из чего вытекает полностью предсказуемый результат —  он был бы таким же, если бы пробел был задан с помощью $S.
--------

А вот с псевдопеременной %CMDCMDLINE%, по крайней мере у меня, глюк — любое обращение к ней с помощью расширенной подстановки меняет её саму. Например, после команды

set var=%cmdcmdline:\=/%

все дальнейшие обращения к %CMDCMDLINE% вернут значение, присвоенное %VAR%. А после команды

rem %cmdcmdline:~2%

из %CMDCMDLINE% исчезнут первые два знака. Причём, в списке процессов можно увидеть, что командная строка меняется на самом деле.

6

Re: CMD/BAT: Хитрости и нелепости интерпретатора

wisgest
Понятно. prompt работает примерно также как и echo: в вывод попадают концевые пробелы.

А вот с псевдопеременной %CMDCMDLINE%, по крайней мере у меня, глюк — любое обращение к ней с помощью расширенной подстановки меняет её саму.

Кое-что из описанного наблюдал. А ведь должна возвращать строку вызова для данной сессии cmd.exe.

( 2 * b ) || ! ( 2 * b )

7

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata пишет:

prompt работает примерно также как и echo: в вывод попадают концевые пробелы.


Кстати, для "prompt" существует недокументированная "заглушка" "$", ставящаяся в конце команды (после кодов приглашения и (или) текста). После неё допустимы не только пробелы, но и комментарии (без символов "&", "|", "<", ">" и символов, вплотную примыкающих к "$" и вместе с ним составляющих код незатребованного приглашения):

for /f %%A in ('
"prompt $E$ ЭТА ФРАЗА НЕ ПОВЛИЯЕТ НА ВЫПОЛНЕНИЕ КОМАНДЫ &for %%B in (1) do rem"
') do @echo:%%A

(приведён код для пакетного файла).



wisgest пишет:

<...> %CMDCMDLINE% <...> — любое обращение к ней с помощью расширенной подстановки меняет её саму.


Развожу руки.

8 (изменено: mljaaa, 2014-01-30 03:35:01)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Команда echo - самый безопасный и надежный вызов с использованием символа двоеточие:

echo:%VAR%

Не катит

set type=Startup Type=2
echo:%type%>>out.txt
pause
С уважением <*>

9 (изменено: Rumata, 2014-01-30 03:45:42)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

mljaaa
Все катит - проблема в "двойке" на конце строки, которая рассматривается интерпретатором как файловый декриптор стандартного потока STDERR. Проверьте следующий код:


setlocal enabledelayedexpansion
set type=Startup Type=2
echo:!type!>>out.txt
pause
endlocal
( 2 * b ) || ! ( 2 * b )

10 (изменено: mljaaa, 2014-01-30 04:06:47)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata пишет:

Все катит - проблема в "двойке" на конце строки, которая рассматривается интерпретатором как файловый декриптор стандартного потока STDERR. Проверьте следующий код:


setlocal enabledelayedexpansion
set type=Startup Type=2
echo:!type!>>out.txt
pause
endlocal

Работает А все дело в "заклинании enabledelayedexpansion"
То-тоже у меня !type! так и писался как !type! :-D

С уважением <*>

11

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Ипи так:

set type=Startup Type=2
>>out.txt echo:%type%
pause

.

12

Re: CMD/BAT: Хитрости и нелепости интерпретатора

mljaaa пишет:

А все дело в "заклинании enabledelayedexpansion"

Не совсем. Проблема в том, как интепретатор работает с переменными окружения. Дело в том, что они (переменные) переменнными не являются - они макрокоманды, которые раскрываются при подстановке. В данном случае выводимая строка содержит на конце 2, которая воспринимается как дескриптор. Вот чтобы "переменные" окружения заработалиименно как переменные, используется команда setlocal enabledelayedexpansion, которая предотвращает раскрытие макросов и сохраняет содержимое нетронутым.

( 2 * b ) || ! ( 2 * b )

13

Re: CMD/BAT: Хитрости и нелепости интерпретатора

По мере возможности стараюсь отойти от использования "setlocal enabledelayedexpansion" из-за проблем с "!", особенно при построчном разборе текста в цикле "for". Поэтому ещё один вариант без "setlocal enabledelayedexpansion":

set type=Startup Type=2
call echo:%%type%%>>out.txt
pause

14

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Yury пишет:

По мере возможности стараюсь отойти от использования "setlocal enabledelayedexpansion"…

В том то и дело, что мера возможности ограничена.

set "type=Startup & Type=2"
call echo:%%type%%>>out.txt

— CALL в пролёте.

15

Re: CMD/BAT: Хитрости и нелепости интерпретатора

wisgest пишет:

В том то и дело, что мера возможности ограничена.


Полностью согласен. Для каждого отдельного случая проблема, в основном, решается:

set "type=Startup ^& Type=2"
call echo:%%type%%>>out.txt
pause

.

А вот в цикле разбора это действительно "подводные камни".

16 (изменено: Rumata, 2014-02-27 13:51:48)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Исследование не претендует на скрупулезность и серьезность. Просто сделано, как сейчас модно говорить, just for lulz. Началось с того, что хотел чуток подправить hrc-схему для batch-файлов в FarColorer. Стало интересно, какой набор символов допустим в именах меток. Как я уже намекнул, я не делал дотошного исследования и не изучил всех воможных вариантов. Поэтому, если у кого-то возникнет желание продолжить и дополнить - оригинальный скрипт в конце этого сообщения.

Здесь набор 100%-допустимых символов. Под допустимостью подразумевается, что
-- символ может находится в любом месте имени метки (в начале, в середине, в конце)
-- метка доступна при любом режиме расширения setlocal
-- метка доступна любым способом (прямое обращение goto/call :LABEL или косвенное обращение, например, goto/call :%1)

Имя метки может состоять из:

-- букв латинского алфавита
-- цифр
-- символа подчеркивания _
-- знаков препинания . (точка), - (дефис), [ и ] (квадратные скобки), { и } (фигурные скобки), / и \ (прямой и обратный слеши)
-- знаков ' и ` (прямой и обратный апострофы), ~ (тильда), @ ("собачка"), # (диез), $ (доллар)

-- ) закрывающая круглая скобка (не может рассматриваться 100%-допустимой. Подробности в обсуждении ниже)

Остальные символы либо совершенно не допустимы либо не имеют 100% поддержку.

Далее программа, для тестов. Тесты простые. Запускаете js-скрипт. Затем запускаете сгенерированный файл test_make.bat. Результат в другом файле - test_done.txt.



var chars 
    = '`123456' + '7' + '890-=' 
    + '~!@#$%^' +       '*()_+' // & is special character in the shell

    + '[]' + '\\' 
    + '{}' // | - absolutely illegal character 

    + ';\'' 
    + ':"' 

    + ',.' + '/' 
    +        '?' // < and > are redirection symbols. Let's exclude them from our tests
    ;

function tmpl(char, index)
{
/*
@echo:==== INDEX ========================================
@echo:==== direct call   : "CHAR"
call :aCHARb 1 2 3
call :aCHAR  1 2 3
call :CHARb  1 2 3
call :CHAR   1 2 3

@echo:==== direct goto   : "CHAR"
@call :L_INDEX_axb
@call :L_INDEX_ax
@call :L_INDEX_xb
@call :L_INDEX_x

@echo:==== indirect call : "CHAR"
@for %%L in ( "aCHARb" "aCHAR" "CHARb" "CHAR" ) do call :%%~L 1 2 3

@echo:==== indirect goto : "CHAR"
@call :L_INDEX "aCHARb"
@call :L_INDEX "aCHAR"
@call :L_INDEX "CHARb"
@call :L_INDEX "CHAR"

@goto :EOF

:L_INDEX
goto %~1

:L_INDEX_axb
goto :aCHARb

:L_INDEX_ax
goto :aCHAR

:L_INDEX_xb
goto :CHARb

:L_INDEX_x
goto :CHAR

:aCHARb
:aCHAR
:CHARb
:CHAR
@echo:[%1] [%*] [%0]
@goto :EOF
*/
    return arguments.callee.toString()
        .replace(/^[\s\S]+\/\*|\*\/[\s\S]+$/g, '')
        .replace(/CHAR/g, char)
        .replace(/INDEX/g, index)
        ;
};

var caller = [];
var called = [];

for (var i = 0; i < chars.length; i++) {
    var c = chars.charAt(i);
    var t = tmpl(c, i);

    caller.push('call :L' + i);

    called.push(':L' + i);
    called.push(t);
}

var fso = new ActiveXObject('Scripting.FileSystemObject');
var f = fso.OpenTextFile('test_make.bat', 2, true, 0);

f.WriteLine('@(');
f.WriteLine(caller.join('\n'));
f.WriteLine(')>test_done.txt 2>&1');
f.WriteLine('@goto :EOF');
f.WriteLine(called.join('\n'));

f.Close();
( 2 * b ) || ! ( 2 * b )

17 (изменено: wisgest, 2014-02-28 01:13:12)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Занимательное исследование!

Rumata пишет:

Здесь набор 100%-допустимых символов.

…Имя метки может состоять из:


-- знаков препинания… ) (закрывающая круглая скобка)…

Закрывающая круглая скобка требует экранирования, если используется внутри составной команды в скобках. Если это считать 100%-й поддержкой, то можно заставить работать и другие символы при должном их экранировании или удвоении: % надо удваивать в GOTO и учетверять в CALL; можно использовать чётное число кавычек, при этом между кавычками могут быть пробелы (скорее, не могут — см. след. сообщение) и специальные символы… вот забавный пример:

call :a"<"b
goto a"<"b
:a"^<"b

:: . . .

call :a" <"b
goto a" <"b
:a" <"b

— в первом случае пришлось экранировать < в самой метке, во втором случае это не обязательно, хотя и допустимо — не пойму, в чём тут дело (кажется, понял — см. след. сообшение).

Rumata пишет:

Остальные символы либо совершенно не допустимы либо не имеют 100% поддержку.

К допустимым символам следует отнести также * и ? — при проверке «indirect call» в CALL вместо меток с этими символами подставляются имена файлов, удовлетворяющие получившимся шаблонам (из-за FOR).

18

Re: CMD/BAT: Хитрости и нелепости интерпретатора

wisgest пишет:

…при этом между кавычками могут быть пробелы и специальные символы… вот забавный пример:

call :a"<"b
goto a"<"b
:a"^<"b

:: . . .

call :a" <"b
goto a" <"b
:a" <"b

— в первом случае пришлось экранировать < в самой метке, во втором случае это не обязательно, хотя и допустимо — не пойму, в чём тут дело.

Кажется, понял и не прав насчёт пробелов: во втором случае собственно метка идёт до первого пробела — остальное можно рассматривать как комментарий. В CALL и GOTO же часть аргумента после пробела тоже не влияет на выбор метки для перехода, но чётность кавычек играет роль и в %0 подпрограммы попадает :a" <"b, т.е. через %0 подпрограмме можно передать дополнительные сведения, если её метка содержит одну кавычку.

19 (изменено: Rumata, 2014-02-27 13:48:36)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

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

Вы правы. Закрывающая круглая скобка не может быть 100% поддерживаемой. Внес соответствующие измененияв свой предыдущий текст.

( 2 * b ) || ! ( 2 * b )

20 (изменено: wisgest, 2014-02-28 01:43:42)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata, а что с «*» и «?»? Мне, конечно, в метках достаточно буквенно-цифровых знаков, подчёркивания и точки, но если стремится к объективности, то это, скорее, допустимые знаки, иначе они не полностью поддерживаются не только CALL, но, например, и ECHO, т.к. следующая команда их никогда не напечатает:

for %%L in ( "a*b" "a*" "*b" "*" ) do echo:%%~L

21 (изменено: Rumata, 2014-02-28 10:44:45)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

wisgest пишет:

Rumata, а что с «*» и «?»?

Но они же исключены из списка допустимых символов в метках. Именно в силу того, метка содежащая эти символы не следует третьему "правилу":  метка доступна любым способом (прямое обращение или косвенное обращение). По такому же принципу я исключил восклицательный знак - при enabledelayedexpansion кое-когда (не помню когда точно) теряется восклицательный знак.

( 2 * b ) || ! ( 2 * b )

22

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Содержимое комментария способно вызвать синтаксическую (неперехватываемую) ошибку:

set a=1
rem comment %a:=%
set a=1
:: comment %a:=%

— второй пример показывает, что содержимое комментариев созданных с помощью двоеточия подвергается синтаксическому разбору также как и REM, и даже более сильно:

:: comment ^
echo 1
echo 2
:: comment ^

echo 3
echo 4

— выведет только 2 и 4.

С помощью двоеточия комментарии можно создавать и не с начала строки:

dir &: comment

— в этом случае при включенном режиме отображения команд (ECHO ON) часть строки, содержащая комментарий, включая предшествующий амперсанд, не отображается.

23

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Содержимое комментария способно вызвать синтаксическую (неперехватываемую) ошибку

Более того, комментарии-двоеточия количеством более одного внутри циклов не допустимы - выводится сообщение вида The system cannot find the drive specified..


for /l %%l in ( 1, 1, 5 ) do @(
:: first line
:: another line
    echo:%%l
)
( 2 * b ) || ! ( 2 * b )

24 (изменено: wisgest, 2014-03-23 09:29:26)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata пишет:

Более того, комментарии-двоеточия количеством более одного внутри циклов не допустимы - выводится сообщение вида Системе не удается найти указанный диск..

Надо уточнить: не внутри циклов, а внутри составных команд, более не одного, а одного подряд.
Попробуем разобраться. Комментарии-двоеточия — строго говоря, испорченные метки.
В двух метках подряд смысла нет. Вне составных команд интерпретатор обрабатывает сценарий построчно и ничего не знает о соседних строках. Составные команды считываются целиком и можно предположить, что в строке идущей после метки или комментария-двоеточия интерпретатор не ожидает увидеть метку и в случае двух двоеточий подряд пытается истолковать команду как команду переключения рабочего диска «буква_диска:» (в связи с появлением ключа /D у команды CD многие успели позабыть о такой).

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

Синтаксическая ошибка в имени файла, имени папки или метке тома.

или

":" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.

Но всё это ошибки не приводящие к немедленному завершению скрипта и даже текущей составной команды. А вот пустая строка или закрывающая скобка после метки или комментария-двоеточия в составной команде недопустимы.

Коль зашла речь о метках внутри составных команд, то ясно, что в связи с построчной обработкой командных файлов переход на такую метку разрушит составную команду. Что при этом произойдёт с закрывающими скобками?
Если перед скобкой есть ещё какие-то непробельные символы то возможны различные случаи:

dir )

— скобка становится аргументом предыдущей команды (его частью),

dir)

— скобка становится частью команды, в большинстве случаев — несинтаксическая ошибка (файл не найден),

(dir))

— синтаксическая ошибка.

Но вот если перед скобкой нет ничего кроме пробельных символов, и последующие символы (если есть) отделены хотя бы одним пробельным (в обоих случаях к пробельным символам приравниваются запятая, точка с запятой и знак равенства), то ошибки не будет и строка не будет обрабатываться и отображаться при включенном ECHO ON —
вот ещё один способ создания комментариев (правда, только вне составных команд);
такой комментарий может быть продолжен на следующую строку с помощью «^».

На самом деле, так же как и с помощью двоеточия, комментарии с помощью закрывающей скобки возможны не с начала строки, если перед скобкой добавить «&» :

dir &) это комментарий

но такая ситуация не должна встретиться при переходе на метку внутри составной команды.

А возможны ли комментарии не до конца строки (например, для отключение части строки при отладке без переформатирования строк или для каких-то ухищрений при смешении в одном файле различных форматов)?
Да, причём при помощи штатной команды REM!
Если после REM без пробела поставить один из знаков

+ [ ] : . \ /

(по тем же соображениям, что и для ECHO «.» и «\» нежелательны,
после «/» не должны следовать
«?» + пробельные символы + дополнительные аргументы),
то следующие за ней спецсимволы будут обрабатываться как в обычной команде:

rem: многострочный^
комментарий >empty.txt & cls

(rem:comment) & dir

— пустой файл будет создан, команды «cls» и «dir» — выполнены.

Исключением является символ перенаправления в конвейер «|» — как слева, так и справа от него такая команда REM вызывает ошибку вида

"rem:" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.

_______________________________________


Rumata пишет:

Очень интересный способ конвертации целых чисел в шестнадцатеричное представление

cmd /c exit /b 3735928559
echo %=ExitCode%

Если код возврата принадлежит отрезку 32...126, то также определена переменная %=ExitCodeAscii%, содержащая символ с указанным кодом. Открыто не мной, можно найти в разных источниках и сообщается здесь лишь для полноты изложения, т.к. ограничение на принимаемые значения делает эту переменную малополезной.
%=ExitCode%, %=ExitCodeAscii% — настоящие переменные окружения в отличии, например, от %RANDOM%, их можно увидеть с помощью команды

set ""

25 (изменено: wisgest, 2014-03-23 09:39:44)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

P.S.

wisgest пишет:

…последующие символы (если есть) отделены хотя бы одним пробельным…

Также закрывающая скобка без соответствующей открывающей будет действовать как начало комментария до конца строки, если непосредственно за скобкой идут открывающая скобка или символы-ограничители команды:

( & | < >
wisgest пишет:

…такой комментарий может быть продолжен на следующую строку с помощью «^».

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

26

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Недокументированная возможность команды SETLOCAL

http://stackoverflow.com/a/15659309/3627676 (обсуждение на форуме dostips)
Скрипт с командой setlocal по завершении выполнения возвращается в первоначальный каталог, даже если в скрипте были переходы с помощью команд cd/pushd, но не было возвратов в исходную точку по cd/popd.

( 2 * b ) || ! ( 2 * b )

27

Re: CMD/BAT: Хитрости и нелепости интерпретатора

http://stackoverflow.com/a/26736458/3627676

Создание нового файла нулевого размера.


break >emptyfile.txt

Команда BREAK внутренняя, поэтому выполняется быстро.

Старый способ тоже использует встроенные средства, но он длинее и не такой лаконичный:


set /p "=" <nul >emptyfile.txt
( 2 * b ) || ! ( 2 * b )

28 (изменено: Rumata, 2014-11-08 17:29:26)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

http://stackoverflow.com/a/26717684/3627676

Способ узнать было ли перенаправление на стандарный ввод скрипта


@echo off

timeout /t 0 >nul 2>nul
if %errorlevel% == 1 echo:stdin
if %errorlevel% == 0 echo:normal

Используется особенность программы TIMEOUT, которая не поддерживает перенаправление ввода/вывода. Может потребоваться в случае, если необходимо различить вариант перенаправления


command | script.bat
script.bat < filename

и обычный запуск


script.bat
( 2 * b ) || ! ( 2 * b )

29

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata пишет:

Создание нового файла нулевого размера.

А:

copy nul "file.ext"

— работает в Windows 7 и выше?

30

Re: CMD/BAT: Хитрости и нелепости интерпретатора

copy nul file.ext

работает и в старенькой ХР. Вот только команда может быть и короче:

cd.>file.ext

31 (изменено: Rumata, 2014-11-08 19:14:45)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Да, кстати, работает.

Вот про copy nul забыл, а про cd. не знал.

( 2 * b ) || ! ( 2 * b )

32

Re: CMD/BAT: Хитрости и нелепости интерпретатора

greg zakharov пишет:

работает и в старенькой ХР.

Про то я знаю, поскольку под ней и сижу . Помнится, вроде как то ли под Windows 8, то ли под Windows Server 2008 R2 не заработало.

33

Re: CMD/BAT: Хитрости и нелепости интерпретатора

alexii пишет:

Про то я знаю, поскольку под ней и сижу

А Вы экстремал

Rumata пишет:

Вот про copy nul забыл, а про cd. не знал.

Странно, что не знали - способ уже замшелый как не знамо что.

34

Re: CMD/BAT: Хитрости и нелепости интерпретатора

greg zakharov пишет:

А Вы экстремал wink

Нищеброд .

35

Re: CMD/BAT: Хитрости и нелепости интерпретатора

"Довесок" к уже упомянутым командам:


@echo off

for %%i in (

 "call"
 "doskey"
 "md nul"
 "sort nul"
 "type nul"

 "echo on"
 "echo off"
 "color"
 "endlocal"
 "setlocal"
 "shift"
 "popd"
 "prompt"
 "set var="
 "title"

 ) do @(
 %%~i>"This empty file was created by using the command ''%%~i''!"
 )

exit /b

.


Первую группу команд, думаю, можно использовать безусловно, а вторую-- в зависимости от ситуации.


К первой группе ещё можно отнести команду "cmd /c".

36

Re: CMD/BAT: Хитрости и нелепости интерпретатора

alexii, тогда как назваться, если WinXP\7 триальные, живут под VirtualBox в Debian?
Yury, способов создания пустого файла много, в ХР, например, можно и через debug, - соль, нужно полагать, здесь не столько в вариативности, сколько в лаконичности.

37 (изменено: Yury, 2014-11-09 11:10:52)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

greg zakharov пишет:

Yury, способов создания пустого файла много, в ХР, например, можно и через debug, - соль, нужно полагать, здесь не столько в вариативности, сколько в лаконичности.


Не совсем так:

Yury пишет:

Первую группу команд, думаю, можно использовать безусловно, а вторую-- в зависимости от ситуации.

То есть, например, если мне нужно почти одновременно применить "SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION" и создать пустой файл, то будет удобнее (и лаконичнее, если хотите) написать:

setlocal enableextensions enabledelayedexpansion>"example.txt"

.

38

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Я бы еще добавил ясность изложения.
Лучше написать так


type nul >filename
copy nul filename >nul

можно и так


call>filename
break>filename

Так как эти команды короче, осмысленнее или отсутствует "сайд-эффекта". Например, cd. трудна для восприятия, нужно задуматься, что тут происходит на самом деле. (хотя break в этом контексте тоже не ахти какая осмысленная команда). setlocal/endlocal лучше оставить для своих прямых обязанностей. В контексте создания пустового файла они выполняют некие дополнительные действия ("сайд-эффект"), а удобство весьма сомнитеьно. В плане лаконичности call лучший кандидат. Это всего лишь мое мнение.

( 2 * b ) || ! ( 2 * b )

39

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Пардон, а где сие

Yury пишет:

setlocal enableextensions enabledelayedexpansion>"example.txt"

применимо? А то мысли всякие нехорошие напрашиваются...

40

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata пишет:

Например, cd. трудна для восприятия...

Ой ли?

41 (изменено: Yury, 2014-11-09 13:06:31)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

greg zakharov пишет:

Пардон, а где сие

Yury пишет:

setlocal enableextensions enabledelayedexpansion>"example.txt"

применимо? А то мысли всякие нехорошие напрашиваются...




@setlocal enableextensions enabledelayedexpansion>"example.txt"

@for %%i in (Мама мыла раму.) do @(
 set x=%%i
 set x=!x:Мама=Папа!
 echo !x:мыла=мыл!>>"example.txt"
 )

@exit /b

Если файл "example.txt" не существует, то он создаётся, если же этот файл существует, то он "опустошается" во избежание дозаписи.



Правда, в этом случае такая необходимость отпадает:


@setlocal enableextensions enabledelayedexpansion

@>"example.txt" (
for %%i in (Мама мыла раму.) do @(
 set x=%%i
 set x=!x:Мама=Папа!
 echo !x:мыла=мыл!
 )
)

@exit /b

.

42

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Yury пишет:

Если файл "example.txt" не существует, то он создаётся, если же этот файл существует, то он "опустошается" во избежание дозаписи.

Простите, но это что-то из области "CMD\BAT: камасутра".

43

Re: CMD/BAT: Хитрости и нелепости интерпретатора

greg zakharov пишет:
Yury пишет:

Если файл "example.txt" не существует, то он создаётся, если же этот файл существует, то он "опустошается" во избежание дозаписи.

Простите, но это что-то из области "CMD\BAT: камасутра".


greg zakharov, излагайти свои мысли так, чтобы они были понятны другим.

44

Re: CMD/BAT: Хитрости и нелепости интерпретатора

greg zakharov пишет:

alexii, тогда как назваться, если WinXP\7 триальные, живут под VirtualBox в Debian?

«Удачливым сукиным сыном» . Ибо пробная версия XP — достаточно большая редкость. У меня нет.

45 (изменено: Yury, 2014-12-18 05:30:24)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata пишет:

Например, cd. трудна для восприятия, нужно задуматься, что тут происходит на самом деле.




cd.

-- это тоже самое, что

cd .

.
Команда изменяет текущий каталог на... текущий каталог.



cd..

-- это тоже самое, что и

cd ..

.
Команда изменяет текущий каталог на родительский каталог.





Rumata пишет:

В плане лаконичности call лучший кандидат.




rem+>1.txt
rem[>2.txt
rem]>3.txt
rem\>4.txt
rem/>5.txt
rem.>6.txt
rem,>7.txt
rem:>8.txt
rem;>9.txt

Всё те же символы, что и для "echo", за исключением "(" и "=".


Команда

rem=>example.txt

равносильна команде

rem >example.txt

,
то есть является обычным помещением комментария.


Удивительно, но знак равенства всё же работает, но только в такой конструкции:

for %%i in ("=") do rem%%~i>10.txt

.


Команда

rem(>example.txt

тоже создаст пустой файл, но с выводом ошибки:

"rem(" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.

.
То есть с таким же успехом пустой файл можно создать с помощью команды

Абракадабра 2>nul>example.txt

.


Кстати, применив команду "rem:" можно одновременно написать нужный комментарий и создать пустой файл. Например, в коде

rem: Мама мыла > раму.

" Мама мыла " -- это комментарий, а "> раму." -- это создание пустого файла "раму".

46

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Yury, странно, что Вам пока не дали статус разработчика.

47 (изменено: Rumata, 2014-12-21 15:32:43)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

http://ss64.com/nt/call.html

Недокументированное поведение команды call.
call команда (без двоеточия в начале) первым делом ВСЕГДА ищет исполнимый файл на диске, а потом запускает внутреннюю команду. То есть call set заведомо медленнее (из-за дисковых операций). То есть в циклических действиях следует избегать использования таких конструкций. Также это может привести к побочному эффекту если такой файл на диске существует! Проверено, это так и есть...

( 2 * b ) || ! ( 2 * b )

48 (изменено: wisgest, 2015-07-13 09:08:20)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Rumata пишет:

То есть call set заведомо медленнее (из-за дисковых операций). <…> Также это может привести к побочному эффекту если такой файл на диске существует! Проверено, это так и есть...

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

добавить к командному файлу подпрограмму

:~
@%*
@exit /b

и вместо CALL КОМАНДА
писать CALL:~ КОМАНДА
, в том числе, если требуется неоднократное раскрытие переменных, вместо нескольких CALL подряд перед командой использовать столько же CALL:~

— Поведение, за исключением возможных побочных эффектов, кажется идентичным,
но не совсем:
а) появляется некоторая возможность использовать IF и FOR после CALL;
б) изменяется поведение GOTO (при последующей встрече с EXIT /B)
и EXIT /B (устанавливается %ERRORLEVEL%, но не происходит выход).

Хотя в последнем нет особой необходимости, но если вдруг понадобится использовать GOTO и EXIT /B с отложенным раскрытием их аргументов и без помощи вспомогательной переменной, то можно для этих команд написать отдельные подпрограммы, использующие переход на несуществующую метку

+ открыть спойлер
:goto
@(goto)2>nul & goto %*
:exit/b
@(goto)2>nul & exit /b %*

и вместо

call goto выражение_для_вычисления_метки
call exit /b выражение_для_вычисления_кода_возврата

писать

call :goto выражение_для_вычисления_метки
call :exit/b выражение_для_вычисления_кода_возврата

P.S. Можно заметить, что этим способом можно было сразу определить подпрограмму «~»:

:~
@(goto)2>nul & %*

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

call:~ exit /b число

для установки кода ошибки без возврата из подпрограммы — более полезной.

49 (изменено: Rumata, 2015-12-28 10:27:08)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

По-видимому, нет возможности простым способом заэкранировать шаблон "?" и рассматривать его как простой символ.


for %f in ( "" "?" "/?" "-?" ) do @( echo:%f )
( 2 * b ) || ! ( 2 * b )

50

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Именно в цикле? >

for /f "delims=" %# in ("^? /? -^?") do @(echo:%#)

51 (изменено: Yury, 2015-12-29 13:03:40)

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Flasher, в Вашем примере экранирование излишне, более того, оно "портит" вывод.

Rumata, да, к сожалению, и мне пока способ отображения символов "?" и "*" и содержащих их строк для этого случая неизвестен.

52

Re: CMD/BAT: Хитрости и нелепости интерпретатора

Yury
Экранирование чего? Совокупность символов может быть любая. И что значит "портит"?