Форум программистов, компьютерный форум, киберфорум
Наши страницы
Batch (CMD/BAT)
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.64/648: Рейтинг темы: голосов - 648, средняя оценка - 4.64
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
#1

Тонкости языка, редкие команды и сложные скрипты

16.10.2012, 06:56. Просмотров 129754. Ответов 94

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

Здесь можете размещать:
  • Ваши статьи;
  • Ссылки на другие статьи (допускаются статьи на английском языке);
  • Редкие ошибки, выдаваемые интерпретатором, способы их устранения/либо причины возникновения.
  • Недокументированные и особые трюки работы с файловой системой, устройствами и т.п.
  • Разрешено обсуждение выложенных здесь материалов (в последствии будут выделены в отдельную тему);
  • Запрещено обсуждение новичками проблем работы с CMD, где вероятная причина - банальная синтаксическая ошибка.


Статьи и тонкости языка:
Основы
  • FAQ по файлам BAT/CMD (статья) ссылка
  • Командная строка Windows (статья) ссылка
  • Особенности реализации командного процессора cmd.exe операционных систем WinNT (статья) сайт
  • Циклические операции и примеры (статья) эта тема
  • Принцип составления однострочных команд Batch (статья) эта тема
Автозапуск
  • Запуск Bat-файла как службы Эта тема
  • Выполнение командного файла перед входом в систему Эта тема
Безопасность и права
  • Элевация прав запуска BAT-файла (отображается диалог контроля учетных записей UAC) ссылка
  • Как запустить командную строку от имени администратора. эта тема
Интерфейс
  • Переключение языка вывода команд консоли на английский ссылка
КомментарийМатематика
  • Деление с выводом дробной части на батниках ссылка
  • Деление через строковую математику (для делимого, превышающего тип данных signed long int) ссылка
  • Получение 16-ричного представления числа эта тема
  • Получение кода символа по таблице ASCII из числового значения byte эта тема
  • Перевод чисел из десятеричной системы в любую (2-16) эта тема
  • Логические операции сравнения для чисел, превышающих арифметику CMD эта тема
Операционная система, реестр
  • Почему нежелательно запускать BAT из 32-битной среды в 64-разрядной системе. ссылка
  • Функции чтения/записи ключа реестра с отображением уровня ошибки ссылка
Переменные и аргументы
  • Подстановка значения переменной в имя или параметр другой переменной эта тема
  • Перебросить значение через локаль эта тема
  • Часто задаваемые вопросы по использованию аргументов командной строки (статья) сайт
  • Получение рабочего каталога на определенном диске эта тема
  • Undocumented Dynamic variables (недокументированные способы раскрытия переменных среды) эта тема
ПотокиПроцессы
  • Получение PID, имени, пути и параметров запуска процесса эта тема
Связь с другими языками программирования и средами, комбинированные батники

  • -- JScript
  • Скомбинированный файл CMD + JS (WSH) эта тема
  • Выполнение JS кода через mshta.exe эта тема
    -- VBScript
  • Передача значения из BAT-сценария в VBS-скрипт эта тема
  • Метод возврата значения из VBS-скрипта в BAT-сценарий эта тема
  • Получение ErrorLevel из команды CMD в переменную VBS-скрипта тема
    -- Реестровый ключ
  • Способ хранения ключа реестра внутри бат-файла эта тема
    -- Ресурсы внутри BAT-файла
  • Распаковка текстовой информации, заданной меткой в файле CMD, во внешний файл тема
  • Встраивание ресурсов в БАТ-файл тема
    -- Другое:
  • Комбинированный файл CMD + KIXTART
  • Объектно-ориентированное программирование на bat ссылка
Текстовые операции и работа с "массивами"
  • Вывод текста без переноса на новую строку (статья) эта тема
  • Чтение текста из файла без пропуска пустых строк эта тема
  • Экранировать восклицательный знак эта тема
  • Получить последний токен в заданной строке эта тема
  • Урезать в строке справа лишние пробелы или другие подряд идущие символы эта тема
  • Получение символов BackSpace (0x08) и Esc (0x27) в переменную эта тема
  • Функция для работы с массивами эта тема
  • Считывание файла в псевдомассив с учетом пустых строк эта тема
  • Функция правильного выравнивания текста по знакам табуляции эта тема
  • Способ передачи в бат-файл параметра содержащего символы & и последующей обработки полученного значения эта тема
Циклы
  • Подстановка переменной в роле модификатора для цикла эта тема
  • Разбиение строки на токены, если разделитель - кавычка эта тема
Файловые операции
  • Объединить 2 файла (сохранив результаты в одном из них) эта тема
  • Получение информации о размере папки эта тема

References, Special Manuals, Книги для High Level Users:
  • Command-line Reference (Microsoft Tech-Net)
  • Недокументированные и малоизвестные возможности Windows XP (книга)
  • Описание встроенных консольных утилит и команд для различных версий ОС dx21.com CMD-Reference

Баги интерпретатора CMD и встроенных команд
Планируется разместить:
Rem не всегда является командой начала комментария
Создание и удаление точек повторной обработки сайт
.

Если у Вас возникли вопросы, создайте новую тему.
16
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.10.2012, 06:56
Ответы с готовыми решениями:

После выполнения определённой команды не выполняются последующие команды
Объясните, пожалуйста, почему может останавливаться выполнение второй и далее...

Тонкости языка С,define
Здравствуйте. Разбираюсь с одной либой для hd44780, есть вопрос по поводу...

Поддерживает ли встроенный сервер PHP скрипты языка Perl?
В PHP существует встроенный сервер. Создаю файл index.html с формой и файл...

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

Как скрипты видят другие скрипты, которые были объявлены ранее?
Может кто-нибудь объяснить как реализовано то, что у нас скрипт, который был...

94
Charles Kludge
Клюг
7641 / 3156 / 382
Регистрация: 03.05.2011
Сообщений: 8,382
16.10.2012, 14:42 #2
Collection of undocumented and obscure features in various MS-DOS versions - переводить лень.

 Комментарий модератора 
К сожалению, в текущей версии интерпретатора практически все описанные вариации команд не работают или вообще не существуют такие утилиты.
2
Charles Kludge
Клюг
7641 / 3156 / 382
Регистрация: 03.05.2011
Сообщений: 8,382
18.10.2012, 12:20 #3
Дык, An A-Z Index of the Windows CMD command line, весьма подробно, например:
Advanced usage - CALL SET
The CALL SET syntax allows a variable substring to be evaluated, read the CALL page for more detail on this technique:
Bash
1
2
3
4
5
SET start=10
 SET length=9
 SET string=The quick brown fox jumps over the lazy dog
 CALL SET substring=%%string:~%start%,%length%%%
 ECHO (%substring%)
Hidden features of Windows batch files - отсюда выудил, например, как сделать inline-комментарий:
Bash
1
echo %DATE% &::однострочный комментарий
 Комментарий модератора 
Весьма удобная фишка!
3
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
27.10.2012, 01:54  [ТС] #4
Способ хранения ключа реестра внутри бат-файла

Bash
1
2
3
4
5
6
7
8
9
REGEDIT4
 
; @ECHO OFF
; CLS
; REG IMPORT "%~f0"
; EXIT
 
[HKEY_CURRENT_USER\Software\Test]
"TestVal"="Succeeded"
Запускает сам себя и импортирует ключ в реестр.
; в CMD интерпретируется как знак пробела.

by Rob Vanderwoude. Спасибо за ссылочку: Charles Kludge.
6
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
13.11.2012, 01:44  [ТС] #5
На тему "Сложные скрипты" (для "разбора полетов"):

Hex_Dump
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
@echo off
:hexDump [/option]... file - dump a file in hex format
::
::  Displays the content of a binary file using a pair of hexadecimal digits
::  for each byte. By default the ouput displays 16 bytes per line, with the
::  bytes (hexadecimal pairs) delimited by a space.
::
::  The format of the dump can be modified by the following case insensitive
::  options:
::
::    /BblockSize   The blockSize after the /B specifies the number of bytes
::                  to print in each block. If the blockSize is <= 0 then /C,
::                  /D, /E, /A and /O options are ignored and the bytes are
::                  output in a continuous stream without any delimiters or
::                  linebreaks.
::                  The default blockSize is 1.
::
::    /CblockCount  The blockCount after the /C specifies the number of blocks
::                  to include on each line of output.
::                  The default blockCount is 16.
::
::    /DbyteDelim   The byteDelim after the /D specifies the delimiter string
::                  to use between bytes within a block.
::                  The default byteDelim is undefined (no delimiter)
::
::    /EblockDelim  The blockDelim after the /E specifies the delimiter string
::                  to use between blocks within a line.
::                  The default blockDelim is "/E " (a single space)
::
::    /SstartOffset The startOffset after the /S specifies the number of bytes
::                  to skip before displaying bytes.
::                  The default startOffset is 0.
::
::    /Nlength      The length after the /N specifies the total number of
::                  bytes to display after the startOffset. The default is to
::                  display up until the end of the file.
::
::    /A            Append the ASCII representation of the bytes to the end
::                  of each line. Non-printable and extended ASCII characters
::                  are displayed as periods.
::
::    /O            Prefix each line with the starting offset of the line in
::                  hexadecimal notation.
::
::    /H            Display hexDump help
::
::  Each option must be entered as a separate argument. Numeric components to
::  options may be specified using any numeric expression supported by SET /A.
::  The option defaults may be modified by presetting a hexDumpDefaults
::  variable.
::
  setlocal enableDelayedExpansion
  set /a blockSize=1, blockCount=16, startOffset=0
  set ascii=
  set offset=
  set len=
  set opts=
  set byteDelim=
  set "blockDelim= "
  set endDefault=
  for %%a in (!hexDumpDefaults! // %*) do (
    if not defined opts (
      set "arg=%%~a"
      if "!arg:~0,1!"=="/" (
        if defined endDefault shift /1
        set "opt=!arg:~1,1!"
        if /i "!opt!"=="B" set /a blockSize=!arg:~2!
        if /i "!opt!"=="C" set /a blockCount=!arg:~2!
        if /i "!opt!"=="D" set "byteDelim=!arg:~2!"
        if /i "!opt!"=="E" set "blockDelim=!arg:~2!"
        if /i "!opt!"=="S" set /a startOffset=!arg:~2!
        if /i "!opt!"=="N" set /a len=!arg:~2!
        if /i "!opt!"=="A" set "ascii=  "
        if /i "!opt!"=="O" set offset=TRUE
        if /i "!opt!"=="H" set "opts=TRUE" & goto :hexDump.help
        if /i "!opt!"=="/" set endDefault=true
      ) else set opts=TRUE
    )
  )
  if "%~1"=="" goto :hexDump.help
  if not exist %1 (
    echo ERROR: File not found >&2
    exit /b 1
  )
  set fileSize=%~z1
  if defined len (
    set /a "endOffset = startOffset + len"
    if !endOffset! gtr %fileSize% set endOffset=%fileSize%
  ) else set endOffset=%fileSize%
  if defined offset set offset=%startOffset%
  if %blockSize% lss 1 (
    set /a "blockSize=0, blockCount=2000"
    set "ascii="
    set "offset="
    set "byteDelim="
    set "blockDelim="
  )
  set dummy="!temp!\hexDumpDummy%random%.txt"
  <nul >%dummy% set /p ".=A"
  set dummySize=1
  for /l %%n in (1,1,32) do (if !dummySize! lss %endOffset% set /a "dummySize*=2" & type !dummy! >>!dummy!)
  set /a "pos=0, cnt=0, skipStart=startOffset+1, lnBytes=blockSize*blockCount"
  set "off="
  set "hex="
  set "txt=%ascii%"
  set map= ^^^!^"#$%%^&'^(^)*+,-./0123456789:;^<=^>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^^^_`abcdefghijklmnopqrstuvwxyz{^|}~
  set hexMap=0123456789ABCDEF
  ::DEFINE INTERNAL MACRO USED SOLELY BY THIS FUNCTION
  setlocal disableDelayedExpansion
 
  set LF=^
 
 
  ::Above 2 blank lines are required - do not remove
 
  set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
 
  set callMacro=for /f %%a in
 
  set addChar= do (%\n%
    set "byte=%%~a"%\n%
    if "!byte!"=="2space" set "byte=  "%\n%
    if defined ascii if "!byte!" neq "  " (%\n%
      set /a "d=0x!byte!-32"%\n%
      if !d! lss 0 set d=14%\n%
      if !d! gtr 94 set d=14%\n%
      for %%d in (!d!) do set txt=!txt!!map:~%%d,1!%\n%
    )%\n%
    if %blockSize% gtr 0 set /a pos+=1%\n%
    if !pos!==%blockSize% set /a "pos=0, cnt+=1"%\n%
    if not !cnt!==!blockCount! (%\n%
      if !pos!==0 (set "hex=!hex!!byte!!blockDelim!") else set "hex=!hex!!byte!!byteDelim!"%\n%
    ) else (%\n%
      set "hex=!hex!!byte!"%\n%
      set cnt=0%\n%
      if defined offset (%\n%
        set off=%\n%
        set dec=!offset!%\n%
        for /l %%n in (1,1,8) do (%\n%
          set /a "d=dec&15,dec>>=4"%\n%
          for %%d in (!d!) do set "off=!hexMap:~%%d,1!!off!"%\n%
        )%\n%
        set "off=!off!: "%\n%
        set /a offset+=lnBytes%\n%
      )%\n%
      set "ln=!off!!hex!!txt!"%\n%
      if %blockSize%==0 (^<nul set /p ".=!ln!") else echo !ln!%\n%
      set hex=%\n%
      set "txt=%ascii%"%\n%
    )%\n%
  )
 
   ::END OF MACRO DEFS
  setlocal enableDelayedExpansion
  for /f "eol=F usebackq tokens=1,2 skip=1 delims=:[] " %%A in (`fc /b "%~dpf1" %dummy%`) do (
    set /a skipEnd=0x%%A && (
      if !skipEnd! geq %startOffset% if !skipStart! leq %endOffset% (
        for /l %%n in (!skipStart!,1,!skipEnd!) do %callMacro% ("41") %addChar%
        %callMacro% ("%%B") %addChar%
        set /a skipStart=skipEnd+2
      )
    )
  )
  for /l %%n in (%skipStart%,1,%endOffset%) do %callMacro% ("41") %addChar%
  if %blockSize%==0 if defined hex (<nul set /p ".=!hex!") & set hex=
  for /l %%n in (1,1,%lnBytes%) do if defined hex %callMacro% ("2space") %addChar%
  del %dummy%
  exit /b
  ::-------------------------------------------------------
  :hexDump.help
    setlocal disableDelayedExpansion
    echo:
    set file="%~f0"
    set beg=
    for /f "tokens=1,* delims=:" %%a in ('findstr /n /r /i /c:"^:hexDump " %file%') do (
      if not defined beg set beg=%%a
    )
    set end=
    for /f "tokens=1 delims=:" %%a in ('findstr /n /r /c:"^[^:]" %file%') do (
      if not defined end if %beg% LSS %%a set end=%%a
    )
    for /f "tokens=1,* delims=[]:" %%a in ('findstr /n /r /c:"^ *:[^:]" /c:"^::[^:]" /c:"^ *::$" %file%') do (
      if %beg% LEQ %%a if %%a LEQ %end% echo: %%b
    )
exit /b 0


Добавлено через 1 час 56 минут
Выполнение полноценного WMI через CMD:
(используется обертка HTA+JavaScript)

Bash
1
2
3
4
5
6
7
8
9
10
11
12
@echo off
setlocal
 
for /f "usebackq delims=" %%i in (
    `@"%systemroot%\system32\mshta.exe" "javascript:try {new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(new String(new Enumerator(new ActiveXObject('WbemScripting.SWbemLocator').ConnectServer('.', 'root\\cimv2').ExecQuery('SELECT LocalDateTime FROM Win32_OperatingSystem WHERE Primary = True')).item().LocalDateTime).substr(0, 8 + 6))}; catch (e){}; close();" ^
    1^|more`
) do set sDateTime=%%i
 
echo %sDateTime%
 
endlocal
exit /b 0
Добавлено через 16 часов 49 минут
Метод возврата значения из VBS-скрипта в BAT-сценарий
(на примере скрипта, который ожидает, пока не будет подключен съемный диск)

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@echo off
(
echo For Each n in CreateObject^("Scripting.FileSystemObject"^).Drives
echo if n.DriveType = 1 And n.IsReady = True Then
echo if Not n.DriveLetter = "A" And Not n.DriveLetter = "B" Then Wscript.Echo n.DriveLetter
echo End if
echo Next
) >"%temp%\_.vbs"
:seek
for /f %%a in ('cscript //nologo "%temp%\_.vbs"') do set FLASH=%%a:
if "%FLASH%"=="" ( 
   set /p="."<nul
   ping -n 2 127.0.0.1 >nul
   goto :seek
)
del "%temp%\_.vbs"
Echo %Flash%
pause
Передача значения из BAT-сценария в VBS-скрипт

Bash
1
start "" wscript.exe //nologo VBScript.vbs "My file.txt"
Содержимое VBScript.vbs
Visual Basic
1
2
3
4
5
if wscript.Arguments.Count=0 then 
    Msgbox "Аргументы не переданы"
  else
    Msgbox "Значение первого переданного аргумента = " & wscript.Arguments(0)
end if
Получение ErrorLevel из команды CMD в переменную VBS-скрипта здесь

Вынесение кода, заданного меткой в скомбинированном BAT-файле можно увидеть здесь
2
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
24.11.2012, 03:55  [ТС] #6
Объединить 2 файла (сохранив результаты в одном из них)

В конец результирующего файла помещает управляющий символ (&1A) вместо переноса каретки.

Bash
1
copy %1+%2
2-й файл присоединится к 1-му. Результат сохранится в 1-м файле.

Bash
1
copy %2+%1
1-й файл присоединится ко 2-му. Результат запишется во 2-м файле.

Цитата Сообщение от Smitis Посмотреть сообщение
Уточнение 3961893
Цитата Сообщение от Dragokas Посмотреть сообщение
В конец результирующего файла помещает управляющий символ (&1A) вместо переноса каретки
Есть ключи /a и /b для копирования, соответственно, текстовых и бинарных файлов. При копировании с ключом /a в конец результирующего файла всегда добавляется символ с кодом &1A (это управляющий символ EOT - End Of Text). Кроме того, текстовые файлы будут обрезаны до символа EOT, если он в них встретится. Бинарные файлы копируются "as is". Без ключей /a и /b команда copy включает некий AI, пытаясь определить текстовый файл или бинарный. Результаты этого AI не всегда адекватны. Поэтому, хорошей привычкой может быть всегда использовать ключ /b, даже при копировании текстовых файлов (дабы избежать появление последнего "мусорного" символа).
2
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
10.12.2012, 00:48  [ТС] #7
Экспериментировал тут с пользовательскими дескрипторами потоков. Добился такого:

Перенаправить потоки вывода StdOut + StdError батника во внешний файл
Bash
1
2
3
4
5
6
7
8
@echo off
::Потоки вывода по-умолчанию всех последующих команд будут перенаправляться в файл out1.txt
Echo. 1>&3 2>&4 3>out1.txt 4>&3
::Создаем вывод в StdOut (дескриптор № 1)
Echo testing
::Имитируем ошибку - вывод в StdError + StdOut (дескрипторы 2, 1)
copy zz:\
pause>con
В результате получится файл out1.txt с текстом testing, сообщениями от команды Copy.
Для принудительного вывода потока на экран следует воспользоваться конструкцией > con
как показано в последней строке.

Еще одним способом является запуск батника через консоль с явным перенаправлением:
Bash
1
batnik.bat 1>out1.txt 2>&1
либо вариант через двойной запуск батника:
Bash
1
2
3
4
5
6
7
8
@echo off
if "%1"=="" (
  Echo Working...
  Call "%~dpnx0" 0 1>nul 2>&1
  Echo Ready...
  Goto :eof
)
::Здесь далее Ваш код
Для дозаписи лога в файл достаточно удвоить знак >>
Bash
1
batnik.bat 1>>out1.txt 2>&1
Для зануления, как всегда можно воспользоваться перенаправлением на устройство Nul
Bash
1
batnik.bat 1>nul 2>&1
Конструкция 2>&1 присоединяет поток вывода ошибок (2) к потоку вывода информационных сообщений (1).
Немного больше информации о потоках: http://microsin.ru/content/view/127/1/
3
gimntut
879 / 182 / 15
Регистрация: 18.07.2011
Сообщений: 257
13.12.2012, 16:07 #8
Перебросить значение через локаль
Есть такой приём:
Bash
1
2
3
4
5
6
setlocal enabledelayedexpansion &:: Локаль начала действовать
set A=Bla-Bla-Bla &:: Присвоение внутри локали
endlocal&set B=%A% &:: Сначала происходит преобразование переменных в значения (локаль ещё действует), 
:: потом выполняется преобразованая команда, т.е. отключается локаль, а потом происходит присвоение,
:: при этом B находится за пределами локали
echo %B% ::& Вуаля!
То же самое, но без комментариев.
Bash
1
2
3
4
setlocal enabledelayedexpansion
set A=Bla-Bla-Bla
endlocal&set B=%A%
echo %B%
4
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
16.12.2012, 03:36  [ТС] #9
Скомбинированный файл CMD + JS (WSH)
Автор: amel27 (OSZone)

(на примере скрипта, который копирует файл из одного места в другое)
Bash
1
2
3
4
5
6
7
8
9
@set @x=0 /*;
@set $f=C:\1\2003.GDB;
@set $d=C:\2\2003.GDB;
 
@cscript //nologo /e:jscript "%0" "%$f%" "%$d%";
@exit /b
 
*/new ActiveXObject("shell.Application").NameSpace(WScript.Arguments(1)).CopyHere(WScript.Arguments(0),16);
//
1
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
21.12.2012, 17:14  [ТС] #10
Деление с выводом дробной части на батниках
Как известно в бат-файлах есть только операция целочисленного деления
и получения остатка от деления. Получить дробное число нельзя. Решил восполнить этот пробел:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
::Деление с выводом дробной части на батниках
@echo on
::Введите ограничение точности (знаков после точки)
::Не более 8 знаков !!! (ограничение арифметики от -2147483647 до 2147483647.)
Set /A Znak=8
::Введите делимое
Set /A n1=7
::Введите делитель
Set /A n2=6
::Разделитель целой и дробной части
Set Delim=.
 
Set /A nC=n1/n2
Set /A nO=%n1% %% %n2%
if %nO%==0 Goto :ret
Set /A nD=nO
For /L %%A in (1,1,%Znak%) do Set /A nD*=10
Set /A nD=nd/n2
:Trim0
Set /A rest=%nd% %% 10
if %rest%==0 (Set /A nd/=10& Goto :Trim0)
Set nd=%Delim%%nD%
:ret
Echo %nC%%nD%
pause>nul
Алгоритм получения дробной части:
Остаток от деления * (10^(знаков после запятой)) / делитель.
Потом убираются лишние концевые нули у дробной части.
1
Smitis
1629 / 338 / 39
Регистрация: 15.10.2012
Сообщений: 529
30.12.2012, 16:06 #11
Комбинированный файл CMD + KIXTART
Код
;@echo off
;echo CMD part1
;kix32 "%~f0" %*
;echo CMD part2
;goto:eof
break on
$=setascii("on")
"KIXTART part"
?
Во втором примере используется комбинированный скрипт, для получения системных даты и времени, не зависимо от региональных настроек. Файл GetDT.cmd:
Код
;@echo off
;if "%~1" == "" goto nopar
;for /f %%i in ('kix32 "%~f0"') do set %1=%%i
;goto:eof
;:nopar
;:: Если переменная не задана, использует _dt_
;for /f %%i in ('kix32 "%~f0"') do set _dt_=%%i
;goto:eof

break on
$=setascii("on")
$time = @time
$date = @date
left($date,4) "-" substr($date,6,2) "-" substr($date,9,2)
"-" left($time,2) "-" substr($time,4,2) "-" substr($time,7,2)
Использование из другого cmd:
Код
@echo off
:: Переменной dt будет присвоено значение вида YYYY-MM-DD-HH-MM-SS
call GetDT dt
echo %dt%
П.С.
Скриптовый язык kixtart в настоящее время незаслуженно забыт. А ведь когда-то MS даже включала его в ResourceKit
1
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
07.01.2013, 03:50  [ТС] #12
Получение информации о размере папки
Взято с OSZONE, переделано мной для совместимости с ОС без локализации (EN).

Развернуть код...

Windows Batch file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Echo Off
SetLocal enabledelayedexpansion
Set DirProg=l:\bash\test
 
Call :GetTemporaryName tmpfile
 
Dir "%DirProg%" /-C /S /A:-D>"%tmpfile%"
for /f %%A in ('find /v /c "" ^< "%tmpfile%"') do Set /A Count=%%A
Set /A Count-=2
For /F "tokens=1-3" %%a IN ('more +%Count% ^< "%tmpfile%"') Do Set dirsize=%%c& Goto :DirSizeExt
:DirSizeExt
Del "%tmpfile%"
 
Set /a dirsizeT=dirsize+0
If Not "%dirsizeT%"=="%dirsize%" Echo Число %dirsize% слишком велико для обработки в CMD&Pause>nul&Exit
Set kb=1024
Set /a mb=kb*kb, gb=kb*kb*kb, dirsizeKB=dirsize/kb, ostKB=dirsize%%kb*100/kb, dirsizeMB=dirsize/mb, ostMB=dirsize%%mb*100/mb
::Set /a dirsizeGB=dirsize/gb, ostGB=dirsize%%gb*10/gb
Echo %dirsize% Б
Echo %dirsizeKB%,%ostKB% кБ
Echo %dirsizeMB%,%ostMB% МБ
::Echo %dirsizeGB%,%ostGB% ГБ
pause
Exit /B
 
:GetTemporaryName %varName%
set sTempName=%temp%\temp%random%.tmp
if exist "%sTempName%" (goto :GetTemporaryName) else (set %1=%sTempName%)


upd.
Еще более коротко:
Windows Batch file
1
2
3
4
5
@Echo Off
SetLocal enabledelayedexpansion
Set Folder=l:\Bash
For /F "tokens=1-3" %%a IN ('Dir "%Folder%" /-C/S/A:-D') Do Set DirSize=!n2!& Set n2=%%c
Echo Size of %Folder% is %DirSize% Bytes.
.
Оригинальная функция
Windows Batch file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Echo Off
SetLocal enabledelayedexpansion
Set DirProg=l:\bash\test
 
For /F "skip=4 tokens=1-3" %%a IN ('Dir "%DirProg%" /-C /S /A:-D') Do (
    If !flag!==1 Set dirsize=%%c
    If "%%b"=="файлов:" (Set flag=1) Else (Set flag=0)
)
Set /a dirsizeT=dirsize+0
If Not "%dirsizeT%"=="%dirsize%" Echo Число %dirsize% слишком велико для обработки в CMD&Pause>nul&Exit
Set kb=1024
Set /a mb=kb*kb, gb=kb*kb*kb, dirsizeKB=dirsize/kb, ostKB=dirsize%%kb*100/kb, dirsizeMB=dirsize/mb, ostMB=dirsize%%mb*100/mb
Rem Set /a dirsizeGB=dirsize/gb, ostGB=dirsize%%gb*10/gb
Echo %dirsize% Б
Echo %dirsizeKB%,%ostKB% кБ
Echo %dirsizeMB%,%ostMB% МБ
Rem Echo %dirsizeGB%,%ostGB% ГБ
Pause>nul
2
Eva Rosalene
T for Trans-
4050 / 1589 / 302
Регистрация: 06.01.2013
Сообщений: 4,179
Завершенные тесты: 2
07.01.2013, 15:13 #13
Функция для работы с массивами
Может быть, кому нибудь будет полезно. Это пример функции для работы с массивами, на случай если стандартный array не работает.

Развернуть код...
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@echo off
setlocal enabledelayedexpansion
call :arrays new H 10
call :arrays set H 8 5
call :arrays get H 8 last
echo %last%
pause>nul
exit
 
:arrays
@echo off
set function_name=%~1
set massive_name=%~2
set array_position=%~3
set last_arg=%~4
 
if "!function_name!"=="" (
 exit /b
)
if !function_name!==new (
 if "!array_position!"=="" (
  exit /b
 )
)
if !function_name!==set (
 if "!last_arg!"=="" (
  exit /b
 )
)
if !function_name!==get (
 if "!last_arg!"=="" (
  exit /b
 )
)
 
if !function_name!==new (
 call :massive_create
 )
if !function_name!==set (
 call :element_set
 )
if !function_name!==get (
 call :element_get
 )
exit /b
 
:massive_create
FOR /L %%a IN (1,1,!array_position!) DO (
 set %massive_name%%%a=0
 )
exit /b
:element_set
set %massive_name%%array_position%=%last_arg%
exit /b
:element_get
set %last_arg%=!%massive_name%%array_position%! 
exit /b


Прим. от Dragokas: нашел еще похожую тему на хабре: http://habrahabr.ru/post/75951/
0
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
07.01.2013, 23:11  [ТС] #14
Получение PID, имени, пути и параметров запуска процесса

1. Получить PID, Path, Parameters, зная имя процесса
2. Получить имя, Path, Parameters, зная ID процесса
3. Получить Path и Parameters, задав фильтр ID процесса + его имя.

Использую инструментарий WMIC.

Обновление v.1.1. (05.04.2013) - теперь путь к программе со спецсимволами (например, скобки) не должен вызывать падения скрипта.
("закавычил" переменные).
Развернуть код...
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@echo off
Setlocal
 
::Получить PID, Path, Parameters по имени процесса
set ProcName=calc.exe
Call :GetProcessInfo "" "%ProcName%" ProcPath ProcParam PID
 
::Получить Name, Path, Parameters по PID процесса
::set PID=5000
::Call :GetProcessInfo "%PID%" "" ProcPath ProcParam ProcName
 
::Получить Path, Parameters по имени процесса и его PID
::set ProcName=calc.exe
::set PID=5000
::Call :GetProcessInfo "%PID%" "%ProcName%" ProcPath ProcParam
 
Echo Process Name = %ProcName%
Echo PID = %PID%
Echo Path = %ProcPath%
Echo Parameters = %ProcParam%
Echo.
pause
goto :eof
 
 
:GetProcessInfo %1-Proccess_PID %2-Process_Name %3-var.Process_Path %4-var.Process_Parameters %5-var.Optional-PID_or_Name
Setlocal EnableDelayedExpansion
::Making Query
if "%~1" neq "" Set Query=ProcessID^^=%~1
if "%~2" neq "" Set Query=Name^^="%~2"
if "%~1" neq "" if "%~2" neq "" Set Query=^^(ProcessID^^=%~1 and name^^="%~2"^^)
if "%~1"=="" if "%~2"=="" Echo Wrong Query. Must be at least 1 parameter %%1 or %%2.& Exit /B 1
for /f "tokens=1* delims==" %%A in (
  'WMIC path win32_process WHERE %Query% GET "CommandLine"^,"ExecutablePath"^,"Caption"^,"Handle" /value^|findstr /BC:"CommandLine" /C:"ExecutablePath" /C:"Caption" /C:"Handle"') do (
  if "%%A"=="CommandLine" Set "ProcParse=%%B"
  if "%%A"=="ExecutablePath" Set "ProcessPath=%%~dpB"
  if "%%A"=="Caption" Set "ProcName=%%B"
  if "%%A"=="Handle" Set "PID=%%B"
)
::Parse Parameters
Set /A n=0& Set Param=
for %%A in (%ProcParse%) do Set /A n+=1& if !n! neq 1 (Set "Param=!Param!%%A ")
EndLocal& (
  if "%ProcessPath%" neq "" Set "%~3=%ProcessPath:~0,-1%"
  if "%Param%" neq "" Set "%~4=%Param:~0,-1%"
  if "%~5" neq "" if "%~1"=="" (set "%~5=%PID%") else (if "%~2"=="" set "%~5=%ProcName%")
)
Exit /B 0
3
Charles Kludge
Клюг
7641 / 3156 / 382
Регистрация: 03.05.2011
Сообщений: 8,382
21.01.2013, 11:56 #15
Цитата Сообщение от Dragokas Посмотреть сообщение
2) Команды "вывести на экран сумму 1 + 1"
Bash
1
2
Set /A n= 1 + 1
Echo %n%
разрывать нельзя, так как значение переменной "n" будет утеряно.
ORLY?
Bash
1
2
3
4
5
Set /A n= 1^
+ 1^
+2^
+3
Echo %n%
 Комментарий модератора 
Имелось в виду выполнять в разных сессиях интерпретатора
За фишку с птичками спасибо. Напомнил, тоже хорошая вещь, когда пишешь длинные запросы.
3
Charles Kludge
Клюг
7641 / 3156 / 382
Регистрация: 03.05.2011
Сообщений: 8,382
22.01.2013, 20:24 #16
Undocumented Dynamic variables (read only)

%__CD__% текущий каталог, с бэкслэшем'\' в хвосте;

%=C:% Текуший каталог на диске C:

%=D:% Текуший каталог на диске D:,E:,F:...(буковку подставите), если к нему было обращение в текущем сеансе CMD.EXE

%=ExitCode% Шестнадцатеричное значение кода возврата по EXIT /B

%=ExitCodeAscii% Символьное (ASCII) представление кода возврата по EXIT /B (допускается код в пределах от 32 до 126).
Windows Batch file
1
2
3
4
5
6
7
8
@echo off
echo %__CD__%
echo %=C:%
set "decimal=%1"
cmd /c exit /b  %decimal%
echo ASCII(как символ) exitcode: %=ExitCodeAscii%
echo Hex exitcode: %=ExitCode%
pause
6
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
22.01.2013, 22:41  [ТС] #17
Клас
0
Миниатюры
Тонкости языка, редкие команды и сложные скрипты  
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
23.01.2013, 02:24  [ТС] #18
Переключение языка команд консоли на английский

Тема: Английский язык в командной строке
0
Eva Rosalene
T for Trans-
4050 / 1589 / 302
Регистрация: 06.01.2013
Сообщений: 4,179
Завершенные тесты: 2
03.02.2013, 14:16 #19
Экранировать восклицательный знак.
Если у вас в программе используется
Bash
1
setlocal enabledelayedexpansion
, то наверняка вставала проблема, как экранировать восклицательный знак, например, для вывода на экран. Стандартным способом он не экранируется, поскольку, скорее всего, раскрывается 2 раза.
Как экранировать:
Bash
1
^^^!
Итак, первый "^" экранирует второй "^", а третий "^" - экранирует сам восклицательный знак первый раз. Во второй раз остаются только "^"(второй) и "!", после чего "!" экранируется.
Bash
1
2
3
4
5
@echo off
setlocal enabledelayedexpansion
echo ^^^!
pause>nul
exit /b
А в кавычках он экранируется так:
Bash
1
set "$=^!"
Также его можно записать в переменную такой строкой:
Bash
1
(set $=^^^!)
и подставлять в нужном месте (даже в кавычках) как !$!
5
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
19.03.2013, 02:08  [ТС] #20
Деление через строковую математику
Отличие от встроенного в CMD деления: исходное число (делимое) может превышать границу для числового типа данных CMD
(актуально для Гигабайтов данных, представленных в виде байтов, для дальнейшего перевода в более удобо-читаемую единицу измерения).

Кликните здесь для просмотра всего текста
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@echo off
SetLocal EnableDelayedExpansion
::Делимое
set Num1=16261316608
::Делитель
Set Num2=1024
::Макс. кол-во знаков после запятой в результате
Set MaxZ=2
 
 
set /a Num1_pos=-1
 
:AddNum1
set /a Num1_pos+=1
::если строка закончилась
if "!Num1:~%Num1_pos%,1!"=="" Goto AfterZiro
Set Num1_part=%Num1_part%!Num1:~%Num1_pos%,1!
if %Num1_part%==00 Set Num1_part=0
Call :TryDiv
Goto AddNum1
 
:AfterZiro
if %Num1_part%==0 goto Div_End
if %MaxZ% neq 0 Set ResultAll=%ResultAll%.
Set Zero_Marker=true
 
:AddZiro
Set /A MaxZ-=1
if %MaxZ% LSS 0 Goto Div_End
echo %Num1_part%
if %Num1_part%==0 goto Div_End
Set Num1_part=%Num1_part%0
Call :TryDiv
Goto AddZiro
 
:Div_End
echo %ResultAll%
 
pause
Goto :eof
 
:TryDiv
Set /a Result=Num1_part / Num2
echo %Num1_part%-%result%
if %Result% neq 0 (
  Set ResultAll=%ResultAll%%Result%
  Set /A Num1_part=Num1_part - Result * Num2
) else (if "%ResultAll%" neq "" if not Defined Zero_Marker Set ResultAll=%ResultAll%0)
Exit /B


Пример довольно прямолинеен, и не оптимизирован. Зато работает верно, надеюсь Просьба - протестировать с разными числами.
Позже будет время - причешу.
4
19.03.2013, 02:08
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.03.2013, 02:08

Редкие программы
тема и тупая, но в институте задали такой вопрос: какие программы считаются...

Lotusscript: редкие конструкции
Здравствуйте, коллеги. Накидайте мне здесь, пожалуйста, хитрых, редких,...

Редкие отключения и сбои ПК
Добрый день! Около 4-ех месяцев назад поменял процессор с i3-3225 на i5-3450...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru