In Windows NT (XP, Vista, 7, 8, 10,…) one is able to write batch files that are interpreted by the Command Prompt (cmd.exe). They can be used to automate file-system tasks such as backups or basic installations and can be used with other command-line utilities as well. The batch files can be considered to be a simple scripting language with logic and jumps. The advantages of using batch files are the ease of writing them, the ability to edit the files without compiling anything, their cross-compatibility across Windows NT Operating Systems and their inherent ability to manipulate file systems due to their basis on MS-DOS. Batch file scripts are not case-sensitive, although strings and data are. The file is controlled by a list of commands separated into lines which are run like normal commands would be at the Command Prompt, although some functionality is different. Batch files can be run from Windows Explorer but the console used to display them closes automatically at the end of the batch file, so a command at the end that prevents instantaneous exit is needed for any remaining output to be read before the console window closes. Although the batch files are able to manipulate their environment, such as color settings and environment variables, the changes are all temporary, as in a standard Command Prompt session. Color settings, however, are retained on later editions of Windows NT. In order to try to learn about batch files, it is useful to understand Command Prompt commands. See: Guide to Windows commands.
The script is kept inside a batch file, with the extension .bat or .cmd. Although .bat is more recognisable, as it was used in the MS-DOS environment that preceded the Command Prompt, the Command Prompt’s interpretations of batch files is very different to the manner of interpreting DOS batch files, and .cmd files are only interpreted by the Command Prompt, so using the .cmd extension prevents mis-use in older environments.
Execution starts at the top of the file and ends at the end. When the end of the file is reached, the file exits to the Command Prompt if it was invoked from there, or the console window closes if it was invoked from Windows Explorer or the START command.
Typically, batch files start with the ‘echo off’ command, which stops the input and prompt from being displayed during execution, so only the command output is displayed. The ‘@’ symbol prevents a command from having input and its prompt displayed. It is used on the ‘echo off’ command to prevent that first command from displaying the input and prompt:
@ECHO OFF
In order to print lines, the ECHO command is used again, but this time with a text parameter other than ‘off’:
ECHO.Hello World!
The period (‘.’) is used to prevent confusion with the attempt to output ON or OFF rather than turn input and prompt displaying on and off. The last line in a code should then be:
ECHO ON
‘Echo on’ will turn the input/prompt display back on, just in case the program exits to the Command Prompt where without the command ‘echo on’, there will be no visible prompt left for use.
HINT: Starting with Windows XP, the ECHO ON command is optional. The command interpreter automatically enables it after the BAT file terminates.
Using the code above, we can make a hello world program like so:
@ECHO OFF ECHO Hello World! ECHO ON
In batch files there are two ways of writing comments. Firstly there is the form:
REM Comment here.
This form is included as it was in the MS-DOS batch file script. The other form is this:
::Comment here.
This form is generally favoured, for being faster to execute and write, and also for being easy to differentiate from normal commands. For this type of comment only two double-colons (‘::’) are needed and the comment ends at the end of the line. Batch files have no multi-line comment types.
You can also add a comment to the end of the command:
command &::Comment here.
In batch scripting, all variables are strings stored in system memory.
Variables are assigned using the SET command. Variables assigned in this manner persist in the System environment alongside predefined Global System variables until the environment in which they are defined is terminated, either through the use of the ENDLOCAL command or the closing of the command prompt session. Care should be taken to avoid ‘overwriting’ Global environment variables such as ‘PATH’ ‘TIME’ ‘DATE’, as other programs can be dependent on them having their ‘proper’ value.
- The use of the command ‘GOTO :EOF’ in an environment where the command ‘SETLOCAL’ has created a child environment implies and effects an ‘ENDLOCAL’ command.
SET name=John Smith
This command creates an environment variable called name, and sets its value to the string «John Smith». White space on either side of the first ‘=’ sign is included in the assignment of both the variables reference name (‘name’ in this instance) and the variables value [Variable names can contain whitespace!]. Trailing whitespace in a variables value is also assigned, which can cause unexpected failure in some scripts if not detected. For this reason, it is recommended to quote the assignment of variables:
SET "name=John Smith"
Variables are generally used within other commands by expanding the reference string with ‘%’ characters marking the beginning and end of the variable reference string:
ECHO %name%
In batch scripting, variables that are expanded using ‘%’ expansion are read [parsed] by the interpreter prior to the line or block being executed. As such, this means the command will execute with the value the variable held prior to the commencement of that section of code. This is especially significant where code blocks are used and the variables value is reassigned within that code block.
A code block in batch scripting occurs when multiple commands are chained together on the same line using ‘&’ to concatenate the commands; as well as within any parenthesised code such as ‘IF’ statements and ‘FOR’ loops.
An example that demonstrates the problem this poses:
@Echo off Set "count=0" For /L %%n in (1 1 3)Do ( Set /A count+=1 Echo %count% ) Echo %count%
Output:
0 0 0 3
There are 2 methods for resolving this. The first and most commonly used is to Enable Delayed Expansion, which allows variables to be expanded using ‘!’ (delayed) expansion:
@Echo off Set "count=0" SETLOCAL EnableExtensions EnableDelayedExpansion For /L %%n in (1 1 3)Do ( Set /A count+=1 Echo !count! ) Echo %count%
Output:
1 2 3 3
Using Delayed Expansion results in the variable being expanded during execution instead of when the command is initially parsed by the interpreter.
The 2nd method of expanding a variables current value during code blocks is to use the ‘CALL’ command to effectively reset the parser during execution of the command so the current value is read.
@Echo off Set "count=0" For /L %%n in (1 1 5)Do ( Set /A count+=1 Call Echo %%count%% ) Echo %count%
The call method is significantly slower, However is useful for dealing with strings that may include ‘!’ characters that the interpreter would attempt to parse as a variable when delayed expansion is enabled. It is not suitable for strings containing Carets ‘^’ as the call command doubles Carets that occur in the command string that follows the Call.
The use of Delayed expansion allows ‘Associated’ variables to be defined using a common reference name with unique indexes to emulate arrays.
This is possible because while Delayed Expansion enabled, expansion of variables occurs in two steps. First, ‘%’ variables are expanded, then ‘!’ variables are expanded. Example:
@Echo off Set "str[1]=one,three,five" Set "str[2]=two,four,six" Setlocal EnableExtensions EnableDelayedExpansion rem for each in 1 2 For %%i in (1 2)Do ( rem reset sub index variable Set "{i}=0" rem for each in variable str[index] For %%G in (!str[%%i]!)Do ( rem increment sub index count Set /A {i}+=1 rem define element '{i}' from str[index] to str[index][subindex] Set "str[%%i][!{i}!]=%%G" ) ) Set Str Goto :Eof
Output:
str[1]=one,three,five str[1][1]=one str[1][2]=three str[1][3]=five str[2]=two,four,six str[2][1]=two str[2][2]=four str[2][3]=six
The set command can also be used for input:
SET /P var=Enter a value for var:
This command displays «Enter a value for var:» and when the user enters the data, var is given that value.
Be aware, if the user presses enter without entering anything then the value in var is unchanged, so for the sake of a prompt it is often best to give a default value, or clear the value for the variable first if it has been used before:
SET var= SET /P var=Enter a value for var:
Below is an example:
@ECHO OFF SET /P answer= Enter name of file to delete: DEL /P %answer% ECHO ON
This batch file gets the name of a file to delete and then uses the DEL command with the prompt parameter ‘/P’ to ask the user if they’re sure they want to delete the file.
The IF command can be used to create program logic in batch files. The IF command allows three basic checks, on the ERRORLEVEL, the equality of two strings, and the existence of a file or folder. The first check on the ERRORLEVEL will check to see if it is greater than or equal to a certain number:
IF ERRORLEVEL 5 ECHO.The ERRORLEVEL is at least 5.
For this style the first parameter is always ERRORLEVEL, and the second is the value it checks against. In this case, if the ERRORLEVEL is at least 5 then the command at the end of the line is executed, outputting the message «The ERRORLEVEL is at least 5.». The second form is a check between two strings:
IF "%str1%"=="Hello." ECHO.The strings are equal.
Here the first parameter is two strings either side of the double ‘=’, symbolising a check to see if they are equal. If the variable str1 is exactly equal to «Hello.», a check which is case-sensitive, then «The strings are equal.» is outputted. In the case that you wish to make the check case-insensitive you would rewrite it as following:
IF /I "%str1%"=="Hello." ECHO.The strings are equal.
Now, for example, str1 could contain «HELLO.» but the check would still result in the command being executed at the end as the check is now case-insensitive. The final basic IF type is the existence check, to see if a file or folder exists.
IF EXIST myfile.txt TYPE myfile.txt
Here if the file «myfile.txt» exists in the current folder then the command TYPE myfile.txt
is executed which displays the contents of «myfile.txt» in the console window.
All of the preceding examples have an optional NOT parameter that can be written after the IF which will execute the command at the end of the line if the condition is not true. For example:
IF NOT EXIST myfile.txt ECHO.File missing.
Which will output «File missing.» if the file «myfile.txt» is not existent in the current folder. There are a few other IF types with command extensions, which can be seen with the IF /?
command at the command prompt.
The ELSE operator can be used with a combination of brackets to provide multi-line logical statements that provide an alternative set of commands if the condition is not true.
IF condition ( commands to be executed if the condition is true ) ELSE ( commands to be executed if the condition is false )
Unlike some languages, in batch files the scripting requires that the lines IF condition (
, ) ELSE (
and )
are written very specifically like that. It is possible, however, to re-write it to use single-line outcomes all on one line:
IF condition (command if true) ELSE command if false
Below is an example of the ELSE operator in use:
@ECHO OFF ::Prompt for input. SET /P answer=Enter filename to delete: IF EXIST %answer% ( DEL /P %answer% ) ELSE ( ECHO.ERROR: %answer% can not be found in this folder! ) ECHO ON
This batch file will delete a file, unless it doesn’t exist in which case it will tell you with the message «ERROR: %answer% can not be found in this folder!».
Unlike in most computer languages, multiple multi-line IF…ELSE style statements can’t be nested in batch files.
You can control program flow using the GOTO statement. Batch files don’t have all elements for structured programming scripting, however some elements of structured programming such as functions can be simulated. The simplest way of controlling program flow, however, is the GOTO statement which jumps to a specified label.
GOTO labelnam
This code will direct program flow to the label labelnam, which is found at the first occurrence of this line:
:labelnam
It is important to remember that labels only store 8 characters, so if a label is longer than 8 characters only the first 8 will be seen. This means the labels labelname1 and labelname2 can’t be distinguished from each other as their only difference occurs past the first 8 characters. Although not strictly incorrect, it is better to avoid using label names longer than 8 characters to avoid these distinguishing problems easily.
Here is the example from earlier redesigned to loop until asked to stop:
@ECHO OFF :prompt ::Clear the value of answer ready for use. SET answer= SET /P answer=Enter filename to delete (q to quit): IF EXIST %answer% ( DEL /P %answer% GOTO prompt ) IF /I "%answer%"=="q" GOTO :EOF ::By this point an error must have occurred as all ::the correct entries have already been dealt with. ECHO.ERROR: Incorrect entry! GOTO prompt ECHO ON
Take note of the command GOTO :EOF
. This command will take the script to the end of the file and end the current batch script.
Runs a specified command for each file in a set of files.
FOR %variable IN (set) DO command [command-parameters]
%variable Specifies a single letter replaceable parameter. (set) Specifies a set of one or more files. Wildcards may be used. command Specifies the command to carry out for each file. command-parameters Specifies parameters or switches for the specified command.
To use the FOR command in a batch program, specify %%variable instead
of %variable. Variable names are case sensitive, so %i is different
from %I.
Batch File Example:
for %%F IN (*.txt) DO @echo %%F
This command will list all the files ending in .txt in the current directory.
If Command Extensions are enabled, the following additional
forms of the FOR command are supported:
FOR /D %variable IN (set) DO command [command-parameters]
If set contains wildcards, then specifies to match against directory
names instead of file names.
FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
Walks the directory tree rooted at [drive:]path, executing the FOR
statement in each directory of the tree. If no directory
specification is specified after /R then the current directory is
assumed. If set is just a single period (.) character then it
will just enumerate the directory tree.
FOR /L %variable IN (start,step,end) DO command [command-parameters]
The set is a sequence of numbers from start to end, by step amount.
So (1,1,5) would generate the sequence 1 2 3 4 5 and (5,-1,1) would
generate the sequence (5 4 3 2 1)
FOR /F ["options"] %variable IN (file-set) DO command [command-parameters] FOR /F ["options"] %variable IN ("string") DO command [command-parameters] FOR /F ["options"] %variable IN ('command') DO command [command-parameters]
or, if usebackq (or useback) option present:
FOR /F ["options"] %variable IN ("file-set") DO command [command-parameters] FOR /F ["options"] %variable IN ('string') DO command [command-parameters] FOR /F ["options"] %variable IN (`command`) DO command [command-parameters]
(The purpose of usebackq is to use a fullname of file-set including the space.)
filenameset is one or more file names. Each file is opened, read
and processed before going on to the next file in filenameset.
Processing consists of reading in the file, breaking it up into
individual lines of text and then parsing each line into zero or
more tokens. The body of the for loop is then called with the
variable value(s) set to the found token string(s). By default, /F
passes the first blank separated token from each line of each file.
Blank lines are skipped. You can override the default parsing
behavior by specifying the optional «options» parameter. This
is a quoted string which contains one or more keywords to specify
different parsing options. The keywords are:
eol=c - specifies an end of line comment character (just one) skip=n - specifies the number of lines to skip at the beginning of the file. delims=xxx - specifies a delimiter set. This replaces the default delimiter set of space and tab. tokens=x,y,m-n - specifies which tokens from each line are to be passed to the for body for each iteration. This will cause additional variable names to be allocated. The m-n form is a range, specifying the mth through the nth tokens. If the last character in the tokens= string is an asterisk, then an additional variable is allocated and receives the remaining text on the line after the last token parsed. usebackq - specifies that the new semantics are in force, where a back quoted string is executed as a command and a single quoted string is a literal string command and allows the use of double quotes to quote file names in filenameset.
Some examples might help:
FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k
would parse each line in myfile.txt, ignoring lines that begin with
a semicolon, passing the 2nd and 3rd token from each line to the for
body, with tokens delimited by commas and/or spaces. Notice the for
body statements reference %i to get the 2nd token, %j to get the
3rd token, and %k to get all remaining tokens after the 3rd. For
file names that contain spaces, you need to quote the filenames with
double quotes. In order to use double quotes in this manner, you also
need to use the usebackq option, otherwise the double quotes will be
interpreted as defining a literal string to parse.
%i is explicitly declared in the for statement and the %j and %k
are implicitly declared via the tokens= option. You can specify up
to 26 tokens via the tokens= line, provided it does not cause an
attempt to declare a variable higher than the letter ‘z’ or ‘Z’.
Remember, FOR variables are single-letter, case sensitive, global,
and you can’t have more than 52 total active at any one time.
You can also use the FOR /F parsing logic on an immediate string, by
making the filenameset between the parenthesis a quoted string,
using single quote characters. It will be treated as a single line
of input from a file and parsed.
Finally, you can use the FOR /F command to parse the output of a
command. You do this by making the filenameset between the
parenthesis a back quoted string. It will be treated as a command
line, which is passed to a child CMD.EXE and the output is captured
into memory and parsed as if it was a file. So the following
example:
FOR /F "usebackq delims==" %i IN (`set`) DO @echo %i
would enumerate the environment variable names in the current
environment.
In addition, substitution of FOR variable references has been enhanced.
You can now use the following optional syntax:
%~I - expands %I removing any surrounding quotes (") %~fI - expands %I to a fully qualified path name %~dI - expands %I to a drive letter only %~pI - expands %I to a path only %~nI - expands %I to a file name only %~xI - expands %I to a file extension only %~sI - expanded path contains short names only %~aI - expands %I to file attributes of file %~tI - expands %I to date/time of file %~zI - expands %I to size of file %~$PATH:I - searches the directories listed in the PATH environment variable and expands %I to the fully qualified name of the first one found. If the environment variable name is not defined or the file is not found by the search, then this modifier expands to the empty string
The modifiers can be combined to get compound results:
%~dpI - expands %I to a drive letter and path only %~nxI - expands %I to a file name and extension only %~fsI - expands %I to a full path name with short names only %~dp$PATH:I - searches the directories listed in the PATH environment variable for %I and expands to the drive letter and path of the first one found. %~ftzaI - expands %I to a DIR like output line
In the above examples %I and PATH can be replaced by other valid
values. The %~ syntax is terminated by a valid FOR variable name.
Picking upper case variable names like %I makes it more readable and
avoids confusion with the modifiers, which are not case sensitive.
this is mainly used to redirect the output of one program to another program
a | b
means execute «a» and what all output «a» gives to the
console — give that as «b» s input
dir | find ".htm"
will give a list of file which contain «.htm» in their names
The output of a command as well as possible errors could be redirected also to files (Note the 2 in front of the >> ):
ACommand >>TheOutputOfTheCommandLogFile.log 2>>TheErrorOutputOfTheCommandFile.log
Functions may be simulated by using labels to control flow of execution, and using an environment variable to return the resulting return value. Labels can be defined at any place in the script and do not need to be referenced. The code following the label will be executed when encountered. Code blocks identified by labels are usually most conveniently placed after the main script has exited (at the end of the file) so that they will not run accidentally, but will be reached only when targeted by a GOTO or CALL statement.
The subroutine construct works because of the following:
- Code identified by a label can be jumped to by using the GOTO built in command
- Using the CALL built in command with a label creates a new invocation of the command processor for the same script, with an implicit GOTO the label
- Using the expression GOTO :EOF closes the current command processor invocation (Same as EXIT /B except the latter allows to specify an ERRORLEVEL)
The structure of a subroutine call looks like this:
CALL :subroutine1 param1 param2 ... ECHO %result% was returned from subroutine1 CALL :subroutine2 param1 param2 ... ECHO %result% was returned from subroutine2 GOTO :EOF REM The above line ends the main invocation of the command processor and so exits the script :subroutine1 SETLOCAL commands using parameters %1, %2, .... and setting %retval% ENDLOCAL & SET result=%retval% GOTO:EOF REM The above line ends the child invocation of the command processor and so returns to just after CALL subroutine1 in the main script :subroutine2 SETLOCAL commands using parameters %1, %2, .... and setting %retval% ENDLOCAL & SET result=%retval% GOTO:EOF REM The above line ends the child invocation of the command processor and so returns to just after CALL subroutine2 in the main script
Bat file with next content outputs «42» as result of execution
:: describes and calls function for multiplication with 2 arguments @ECHO OFF CALL :multiply 21 2 ECHO %result% :multiply SETLOCAL set retval=0 set left=%1 set right=%2 :: use '/A' for arithmetic set /A "retval=left*right" ENDLOCAL & SET result=%retval% GOTO :EOF
Note:
- Using CALL with a label or the expression CALL :EOF or EXIT /B requires command extensions to be enabled.
- A label is a line consisting of a valid name (not containing any separators such as space or semicolon) prefixed by a colon.
let’s say we want to call a program «MyProgram» from the command prompt. we type the following into our prompt (the .exe file extension is unnecessary):
C:\>myprogram.exe
And this will run the myprogram executable. Now, let’s say we want to pass a few arguments to this program:
C:\>myprogram arg1 arg2 arg3
Now, if we go into the standard main function, we will have our argc and argv values:
int main(int argc, char *argv[])
Where:
argc = 4 argv[0] = "myprogram" (the name of the program - deduct 1 from argc to get the number of arguments) argv[1] = "arg1" argv[2] = "arg2" argv[3] = "arg3"
This shouldn’t come as a big surprise to people who have any familiarity with standard C programming. However, if we translate this to our WinMain function, we get a different value:
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR CmdLine, int iCmdShow)
we will only have one value to accept the command line:
CmdLine = "myprogram arg1 arg2 arg3".
We can also use the function GetCommandLine to retrieve this string from any point in the application. If we want to parse this into a standard argv/argc pair, we can use the function CommandLineToArgvW to perform the conversion. It is important to note that CommandLineToArgvW only works on unicode strings.
When we return a value from our C program, that value gets passed to the CMD shell, and stored in a variable called «ERRORLEVEL». ERRORLEVEL is the only global variable that is not a string, and it can contain a number from 0 to 255. By convention, a value of zero means «success», while a value other then zero signifies an error.
Let’s say we wanted to write a C program that returns the number of arguments passed to it. This might sound like a simple task in C, but it is difficult to accomplish in batch script:
int main(int argc, char *argv[]) { return (argc - 1); }
And we will name this program «CountArgs.exe». Now, we can put this into a batch script, to pass it a number of arguments, and to print out the number passed:
countargs.exe %* ECHO %ERRORLEVEL%
We can, in turn, call this script «count.bat», and run that from a command prompt:
C:\>count.bat arg1 arg2 arg3
and running this will return the answer: 3.
NOTE: Actually, this can be accomplished with a batch file without resorting to a C program, by simply using CMD delayed variable expansion via the «/V:ON» parameter:
/V:ON Enable delayed environment variable expansion using ! as the delimiter. For example, /V:ON would allow !var! to expand the variable var at execution time. The var syntax expands variables at input time, which is quite a different thing when inside of a FOR loop.
Then use a simple batch file like the following to count parameters:
set COUNT=0 for %%x in (%*) do ( set /A COUNT=!COUNT!+1 ) echo %COUNT%
Or an easier way, without having to enable & use ‘delayed environment expansion’, would be to do the following:
set COUNT=0 for %%x in (%*) do set /A COUNT+=1 echo COUNT = %COUNT%
This returns the same answer as the C program example.
Загрузить PDF
Загрузить PDF
Чтобы выполнить описанные в этой статье шаги, сначала запустите Блокнот; для этого нажмите «Пуск» > «Выполнить» и введите «notepad». Сверните окно Блокнота и откройте командную строку; для этого нажмите «Пуск» > «Выполнить» и введите «CMD».
-
В Блокноте можно создать текстовый файл и сохранить его в любом формате. Командная строка предназначена для ввода команд, которые управляют различными функциями системы.
- Щелкните правой кнопкой мыши по синей полосе вверху окна командной строки и в меню выберите «Свойства». Теперь в разделе «Правка» вкладки «Общие» установите флажок у «Быстрая правка». Нажмите OK. Откроется окно с вопросом, хотите ли вы применить или сохранить изменения. Установите флажок у «Сохранить параметры для окон с таким же названием» и нажмите OK.
-
Скорее всего, сейчас вы думаете, что своими действиями повредите систему — это возможно, если не знать, что делать. Поэтому сначала научитесь перемещаться между каталогами.
- Введите CD c:\ и нажмите ↵ Enter. Вы перейдете из текущего каталога в корневой каталог диска C:. Далее мы научим вас отображать все файлы и папки, которые находятся в этом каталоге.
- Введите DIR и нажмите ↵ Enter. На экране отобразится список файлов и папок. В последнем столбце вы найдете имена каталогов, ответвляющихся от корневого каталога диска C: (или от каталога, в котором вы находитесь в данный момент). Если это папка, вы увидите
<dir>
в столбце слева от столбца с именем в той же строке. Если это файл, возле него вы не увидите<dir>
, но найдете расширение файла (*.txt, *.exe, *.docx) в конце имени файла.
-
3
Создайте папку, в которую скопируете все свои пакетные файлы. Введите MKDIR mybatch. Будет создана папка «mybatch». Чтобы проверить это, введите DIR еще раз и найдите эту папку в отобразившемся списке.
-
Если компьютер не подключен к интернету, пропустите это шаг. Команда «Ping» отправляет пакеты данных на указанный сайт и принимает ответы с сайта; если это так, сайт работает нормально.
- Например, проверим, работает ли сайт google.com. Введите PING Google.com и нажмите ↵ Enter. На экране отобразится что-то вроде «Ответ от 72.14.207.99: число байт = 32 время = 117мс TTL = 234». Таких строк может быть около четырех. Если на экране отобразилось сообщение об ошибке, не работает либо ваше интернет-соединение, либо веб-сайт. Также будет указано, сколько пакетов отправлено, получено и потеряно. Если потеряно 0 пакетов, веб-сайт работает на 100 %.
-
Например, введите mspaint.exe, чтобы запустить программу Paint. Труднее открыть программу, которая находится в определенном каталоге, как вы уже сделали с командной строкой и Блокнотом с помощью графического интерфейса пользователя.
- Запустите программу или откройте файл, которые находятся в каталоге. Перейдите в запущенный Блокнот и введите Привет, мир!. Затем нажмите «Файл» > «Сохранить как», в строке «Имя файла» введите «Helloworld.txt» и сохраните файл в папке «mybatch» на диске C:. Перейдите в командную строку, и вы окажетесь в папке «Documents and setting». Теперь введите cd c:\mybatch, нажмите ↵ Enter, а затем введите helloworld.txt. Обычно командную строку еще раз отрывать не нужно, но здесь все немного сложнее, потому что вы не переходите сразу в каталог «C:».
-
». Чтобы удалить папку, используйте команду RMDIR. Например, введите RMDIR deleteme, чтобы удалить папку «deleteme». Эта команда удаляет файлы, папки и подпапки.
- Совет: когда будете пользоваться командой RMDIR, перейдите в папку с файлом или подпапкой, которые хотите удалить, а затем введите RMDIR *, где вместо «*» введите имя удаляемых файла или папки. Перейдите на диск C: и введите RMDIR deleteme. Система поинтересуется, хотите ли вы удалить папку. Нажмите клавиши Y > ↵ Enter. Так вы удалите папку «deleteme».
-
8
Переименуйте файл или папку. Для это воспользуйтесь любой из двух команд: REN и RENAME. Создайте папку «idon’tlikemyname», а затем введите REN idon’tlikemyname mynameisgood. Папка будет переименована. Теперь ее можно удалить.
-
Разберитесь с пакетным программированием и напишите программу в Блокноте. Для этого не нужно покупать дорогую программу — все можно сделать бесплатно. В блокноте введите:
- На экране отобразятся три предложения. При этом сами команды вы не увидите — это благодаря команде @echo off. Без этой команды на экране отобразятся текст и команды, например, так:
- Команда time /t выведет на экран текущее время. Обязательно добавьте параметр «/t» — в противном случае система попросит вас ввести время.
- Нажмите «Файл» > «Сохранить как», в строке «Имя файла» введите «Timefirst.bat» и сохраните файл в папке «mybatch». Обратите внимание, что вы сохранили файл в формате BAT, а не как текстовый файл (ТХТ-файл). Это формат пакетных файлов, которые не работают без расширения «.bat».
@echo off Echo Это пакетный файл, Echo который отображает время Echo Текущее время Time /t
Реклама
4
9
Советы
- Чтобы вывести на экран список всех команд, введите «help».
Реклама
Предупреждения
- Если вы не знаете, что делаете, вы можете повредить систему.
- Используя команду DEL (или DELETE), помните, что файлы/папки удаляются навсегда, то есть в Корзину не попадают.
Реклама
Об этой статье
Эту страницу просматривали 28 877 раз.
Была ли эта статья полезной?
Окружение: операционная система «Windows 10».
Ранее я написал ряд постов, посвященных изучению языка программирования C++ по учебнику Роберта Лафоре. В тех статьях я разбирал примеры и упражнения и выполнял их в интегрированной среде разработки (IDE), в качестве которой использовал «Microsoft Visual Studio». В то время я использовал бесплатную версию этой среды «Visual Studio Community 2017», а сейчас использую «Visual Studio Community 2022» (версия 17.5.3 от 21 марта, самая свежая на сегодня).
Начинающим изучать язык программирования C++ вполне себе можно стартовать с установки этой среды и работе в ней. (Следует иметь в виду, что у среды «Microsoft Visual Studio» есть ряд отличных альтернатив, я вовсе не хочу сказать, что изучение языка C++ в среде «Microsoft Visual Studio» — это единственный путь для начинающего.) У этой среды есть как свои достоинства, так и свои недостатки. Самый большой ее недостаток, на мой взгляд, в том, что она очень большая и неповоротливая, требует достаточно мощного компьютера. При этом бо́льшая часть инструментов этой среды начинающими не используется.
Одной из хороших альтернатив работе в интегрированной среде разработки для начинающего является работа с компилятором языка C++ из командной строки. Этот способ подходит тем, у кого слабый компьютер, который не тянет работу с большой IDE вроде «Microsoft Visual Studio». Бывают и другие причины для выбора работы из командной строки. (В принципе, на мой взгляд, начинающему изучать язык программирования C++ имеет смысл поработать и в IDE, и научиться работать из командной строки.)
Так же, как в случае работы в интегрированной среде разработки, для работы с кодом программ на языке C++ из командной строки есть ряд альтернатив, но в этом посте я буду описывать работу с компилятором «Microsoft Visual C++», который больше известен под аббревиатурой «MSVC».
Microsoft C++ Build Tools
Для работы из командной строки компания «Microsoft» предлагает набор инструментов (программ и скриптов) для сборки (Build Tools), который называется «Microsoft C++ Build Tools» (он же «Visual Studio Build Tools» или «Build Tools for Visual Studio» и тому подобное). Этот набор инструментов включает в том числе упомянутый выше компилятор «MSVC» и другие нужные для сборки кода на языке C++ инструменты.
В общем, набор инструментов «Microsoft C++ Build Tools» можно загрузить отдельно, либо его же можно загрузить в составе дистрибутива среды «Microsoft Visual Studio», если при установке этой среды выбрать рабочую нагрузку (workload), предназначенную для работы с кодом на языке C++ (например, «Desktop development with C++» или что-то вроде этого, название может слегка отличаться или быть на другом языке общения). Это значит, что в командной строке вы получаете те же самые инструменты, которые использует интегрированная среда разработки.
Набор инструментов «Microsoft C++ Build Tools» вы тоже можете использовать бесплатно (как и версию «Community» среды «Microsoft Visual Studio»), но там есть ограничения. Насколько я понимаю, для обучения и разработки программ с открытым исходным кодом этот набор инструментов точно можно использовать бесплатно (тут подробнее). Вот откуда можно загрузить к себе на компьютер этот набор инструментов для использования без IDE:
https://visualstudio.microsoft.com/visual-cpp-build-tools/
https://visualstudio.microsoft.com/downloads/?q=build+tools
У меня, как я упомянул в начале поста, установлена среда «Visual Studio Community 2022» с рабочей нагрузкой, предназначенной для работы с кодом на языке C++. Поэтому в моем случае нет необходимости устанавливать набор инструментов «Microsoft C++ Build Tools» отдельно. Я уже и так имею возможность работать с компилятором «MSVC» как из IDE, так и из командной строки.
Порядок запуска компилятора «MSVC» из командной строки
Компания «Microsoft» не рекомендует запускать инструменты из набора «Microsoft C++ Build Tools» из обычной программы-оболочки с командной строкой, как мы привыкли, так как для этого набора инструментов задействуется много разных переменных среды, которые должны быть правильно настроены. По крайней мере, начинающим этого точно делать не сто́ит.
Для запуска набора инструментов «Microsoft C++ Build Tools» предлагается использовать предварительно настроенные нужным образом версии программ-оболочек, которые можно запустить из меню кнопки «Пуск» операционной системы «Windows 10». В этом меню нужные пункты будут присутствовать, если вы установили набор инструментов «Microsoft C++ Build Tools» либо отдельно, либо в составе интегрированной среды разработки «Microsoft Visual Studio».
У меня в меню кнопки «Пуск» операционной системы присутствуют два подходящих пункта-ярлыка. Их можно быстро найти, набрав в поиске операционной системы (кнопка с увеличительным стеклом рядом с кнопкой «Пуск» на панели задач) слово «developer»:
– Developer Command Prompt for VS 2022
– Developer PowerShell for VS 2022
Первый из них использует программу-оболочку «cmd.exe», а второй — программу-оболочку «Windows PowerShell». Можно запустить любой из этих ярлыков и далее уже работать в открывшейся программе-оболочке, там всё будет настроено так, как следует.
Оба эти ярлыка в качестве хоста используют программу-«эмулятор терминала» «Windows Console», так как я работаю в операционной системе «Windows 10». Но мне уже полюбилась программа-«эмулятор терминала» «Windows Terminal» (предполагается, что «Windows Terminal» заменит «Windows Console» в операционной системе «Windows 11», но у меня нет доступа к «Windows 11», поэтому я не знаю, как оно там), поэтому я предпочитаю запустить ее и открыть программу-оболочку «Developer PowerShell for VS 2022» уже из нее. (У меня, кстати, есть ряд постов про программу-«эмулятор терминала» «Windows Terminal».)
К слову, программу «Windows Terminal» можно загрузить к себе на компьютер бесплатно и она «увидит» все имеющиеся на компьютере программы-оболочки, после чего любую из них можно будет запустить из программы «Windows Terminal».
На практике
Создаю новую папку «test» в местоположении «C:\Users\Илья\source\repos» с помощью программы «Проводник Windows». В принципе, отдельную папку можно не создавать, но я привык для каждой новой задачи (проекта) создавать новую папку, это удобно и это популярный метод работы. Также отмечу, что папку можно создать в любом месте, но я работаю с кодом программ в указанном выше местоположении, мне так удобно.
Перехожу в программе «Проводник Windows» в созданную папку «test» в местоположении «C:\Users\Илья\source\repos». С помощью редактора кода (я использую «Notepad++» или «VS Code», они оба хороши для небольших программ) создаю текстовый файл «first.cpp» в кодировке UTF-8 с сигнатурой (она же — метка BOM). (К сожалению, компилятор «MSVC» принимает файлы в кодировке UTF-8 только с меткой BOM, тут про это подробнее.) Сохраняю в этом файле следующий код (из учебника Лафоре, с добавленными мною измененениями):
#include <io.h> // для функции _setmode #include <fcntl.h> // для константы _O_U16TEXT #include <iostream> using namespace std; int main() { // переключение стандартного потока вывода в формат Юникода _setmode(_fileno(stdout), _O_U16TEXT); wcout << L"У каждой эпохи свой язык\n"; return 0; }
Из контекстного меню (открывается щелчком правой кнопки мыши) запускаю программу-«эмулятор терминала» «Windows Terminal» и создаю в ней новую вкладку с нужной программой-оболочкой:
Как видно на иллюстрации выше, список доступных программ-оболочек можно открыть, нажав на кнопку со значком уголка, направленного вниз, или нажав соответствующее сочетание клавиш на клавиатуре. (При запуске программы «Windows Terminal» автоматически запускается вкладка с программой-оболочкой по умолчанию, у меня это программа-оболочка «PowerShell». Но в данном случае она не нужна и эту первую вкладку можно закрыть.) Вот что получилось:
Далее работаем из командной строки этой программы-оболочки. Сначала предлагается проверить работоспособность компилятора «MSVC». Исполняемый файл этого компилятора называется «cl.exe», поэтому для его запуска нужно использовать команду «cl»:
PS C:\Users\Илья\source\repos\test> cl Оптимизирующий компилятор Microsoft (R) C/C++ версии 19.35.32216.1 для x64 (C) Корпорация Майкрософт (Microsoft Corporation). Все права защищены. использование: cl [ параметр... ] имя_файла... [ /link параметр_компоновки... ]
Приведенный в блоке кода выше выведенный компилятором текст не содержит сообщений об ошибках, а содержит только информацию о владельце программы и короткую инструкцию по использованию компилятора. Значит, все настройки правильные, можно начинать работу.
Создадим из нашей маленькой программы «first.cpp» исполняемый файл:
PS C:\Users\Илья\source\repos\test> cl /EHsc "first.cpp" Оптимизирующий компилятор Microsoft (R) C/C++ версии 19.35.32216.1 для x64 (C) Корпорация Майкрософт (Microsoft Corporation). Все права защищены. first.cpp Microsoft (R) Incremental Linker Version 14.35.32216.1 Copyright (C) Microsoft Corporation. All rights reserved. /out:first.exe first.obj
В нашей папке «test» появилось два новых файла: «first.obj» и «first.exe». Как известно, процесс сборки программы из исходного кода в исполняемый файл обычно проходит в два этапа: 1) компиляция (выполняется компилятором); 2) «линковка», она же «компоновка» (выполняется «линкером», он же — «компоновщик»). На первом этапе из исходного кода (у нас — единственный текстовый файл «first.cpp») создается объектный файл (в нашем случае — «first.obj»). На втором этапе из объектного файла создается исполняемый файл.
Как видно из результата работы компилятора выше, он сначала делает свою работу (создает объектный файл «first.obj»), а затем автоматически запускает линковщик, который создает из объектного файла исполняемый файл. В принципе, компилятор можно заставить не запускать линковщик автоматически с помощью ключа /c
. Тогда нужно будет запускать линковщик отдельно, вторым этапом, с помощью команды «link» (исполняемый файл линковщика называется «link.exe»). Такой подход бывает нужен в сложных случаях.
Ключ /EHsc
определяет модель обработки ошибок, которая должна быть использована при компиляции. Это рекомендуемый ключ для начинающих.
Вообще у компилятора и компоновщика огромное количество разнообразных ключей, с помощью которых можно выполнить бесчисленное количество разных настроек. Вот тут можно посмотреть на все ключи компилятора «MSVC», перечисленные по алфавиту, чтобы иметь представление о масштабах этого кошмара. Рассмотрение этих ключей, или хотя бы самых полезных из них выходит за рамки этого поста.
Размеры полученных файлов:
PS C:\Users\Илья\source\repos\test> dir Каталог: C:\Users\Илья\source\repos\test Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 04.04.2023 15:16 423 first.cpp -a---- 04.04.2023 15:52 231424 first.exe -a---- 04.04.2023 15:52 122560 first.obj
Как видно из блока кода, приведенного выше, исполняемый файл «first.exe» получился просто огромного размера, если соотнести размер в 226 Кб с тем, что эта программа делает (всего лишь выводит в окно консоли короткую строку). К примеру, если этот же исходный код в файле «first.cpp» скомпилировать в исполняемый файл в среде «Microsoft Visual Studio», то у меня получился исполняемый файл размером 12 Кб, что почти в 19 раз меньше.
Такая большая разница в размерах исполняемого файла получается из-за того, что среда «Microsoft Visual Studio» использует ключи компилятора, предназначенные для оптимизации размера исполняемого файла. Тема оптимизации — это тема не для начинающих. Кому интересно, можно начать изучение этого вопроса отсюда. На период изучения языка C++ по учебнику на размер исполняемого файла можно не обращать внимания. Но при создании реальных полезных программ вопрос оптимизации придется изучить досконально.
Запуск исполняемого файла на выполнение:
PS C:\Users\Илья\source\repos\test> .\first У каждой эпохи свой язык
Как видим из блока кода выше, всё в порядке, программа выполнила свою работу, вывела в окно консоли нужную строку на русском языке.
Отмечу, что приведенный выше исходный код в файле «first.cpp» не является кроссплатформенным, но такая задача не ставилась и этот вопрос выходит за рамки данного поста.
Полезная статья, один из главных источников информации для данного поста: «Walkthrough: Compiling a Native C++ Program on the Command Line» (по-русски «Быстрое ознакомление: компиляция программы на C++ в командной строке»).
В статье рассматриваются примеры практического использования в bat-файлах команд for, echo, goto, определения функций, экранирования символов, определения каталога запуска и многое другое.
Мы все любим писать серьезные вещи на серьезных языках. Шаблоны, C++, Reflection, Perl и многое другое – вот то, что мы любим, то, чему посвящаем длинные сообщения в форумах, то, что снится нам по ночам.
Однако в нашей повседневной деятельности встречаются и вещи, которые не так интересны и интеллектуальны. Мы не очень любим говорить об этом, делаем вид, что Это – грязно, нечистоплотно и недостойно нашего внимания. Однако, приходит день, приходит час и перст Судьбы находит нас – нам надо написать еще один батничек… Иногда это запускалка для построения проекта, которая должна при ошибке компиляции скопировать логи на сетевой диск, иногда – запуск обновления исходных текстов из SVN. Иногда – что-нибудь еще.
К чему я это все? А к тому, что поговорим мы о полезных хитростях при написании файлов сценариев на встроенном командном языке Windows. К счастью, это занятие не является доминирующим в профессиональной деятельности автора, так что я не обязуюсь заполнить абсолютно все пробелы в данной области. Кроме того, рожденный ползать летать не может, и из cmd.exe, увы, не получится ни /usr/bin/perl, ни даже /bin/sh. Так что, все нижеприведенное – просто некоторые интересные факты из жизни файлов с расширением bat, на которые автор обратил внимание во время решения различных практических задач автоматизации.
Наш урок будет построен по сугубо практическому принципу, известному в народе как Cookbook. Иными словами, я не буду вдаваться в синтаксические и семантические дебри командного языка Windows, а лишь продемонстрирую его возможности (хотел написать «мощь», но все-таки передумал). Именно поэтому большинство следующих заголовков будет начинаться со слова «Как». Впрочем, для полноты по ходу развития событий будут даваться подробные комментарии, в том числе и по языковым конструкциям.
Практически все описанные здесь рецепты подойдут только для Windows 2000 и старше. Bat-язык Windows 9x, к счастью, можно считать почившим, так что здесь он не рассматривается. Более того, диалекты cmd.exe операционных систем Windows 2000, Windows XP и Windows Server 2003 также немного различаются. Все приведенное ниже создано и проверено на компьютере под управлением операционной системы Windows XP. За подробной информацией по различиям в реализации той или иной команды обращайтесь к [1].
Как экранировать символ?
В командном языке Windows существует некоторый набор символов с высоким приоритетом, которые всегда трактуются как спецсимволы. К ним, в частности, относятся:
- Операторы перенаправления ввода-вывода <, >, >>.
- Оператор конвейера |.
- Операторы объединения команд ||, & и &&.
- Оператор разыменования переменной %…%.
В случае если символ, относящийся к одному из таких операторов, должен быть включен в вашу команду в его литеральном смысле, вас ждут определенные неожиданности. Например, при выполнении вот такой строки
echo The ratio should be up to 10%
символ процента будет «съеден» интерпретатором, который решит, что это попытка вывода значения какой-то переменной. В случае со знаком процента решение довольно хорошо известно и состоит в удвоении этого символа:
echo The ratio should be up to 10%%
после чего все заработает так, как надо. Однако в других случаях все менее очевидно. Рассмотрим командный сценарий, который генерирует незатейливый HTML-файл:
@echo off set OUTPUTFILE=%1 echo <html> >%OUTPUTFILE% echo <head> >>%OUTPUTFILE% echo <title>This is a greeting page</title> >>%OUTPUTFILE% echo </head> >>%OUTPUTFILE% echo <body> >>%OUTPUTFILE% echo Hello World! >>%OUTPUTFILE% echo </body> >>%OUTPUTFILE% echo </html> >>%OUTPUTFILE%
К сожалению, при попытке запуска этого «чуда инженерного разума» нас постигнет неудача в виде сообщения об ошибке «was unexpected at this time».
Оно и понятно: командный интерпретатор не в силах разобраться, где его просят вывести на экран символ HTML-тега, а где перенаправить вывод. В нормальных языках программирования эта проблема обычно решается обрамлением строковых литералов кавычками. Отчасти это помогает и в bat-файлах. Но лишь отчасти. Выполнение строки
echo "<html>" >%OUTPUTFILE%
приведет к тому, что в выходной файл будут записаны и сами кавычки. Это явно не совсем то, что требуется.
К счастью, есть один малоизвестный способ, позволяющий добиться требуемого результата. Символ ^ позволяет экранировать любой другой символ с безусловным приоритетом. Таким образом, вышеприведенный пример генерации HTML может быть успешно записан так:
@echo off set OUTPUTFILE=%1 echo ^<html^> >%OUTPUTFILE% echo ^<head^> >>%OUTPUTFILE% echo ^<title^>This is a greeting page^</title^> >>%OUTPUTFILE% echo ^</head^> >>%OUTPUTFILE% echo ^<body^> >>%OUTPUTFILE% echo Hello World! >>%OUTPUTFILE% echo ^</body^> >>%OUTPUTFILE% echo ^</html^> >>%OUTPUTFILE%
Таким же способом можно экранировать любой другой специальный символ. Очевидно, можно экранировать и сам ^. Не очень эстетично, зато дешево и практично. Слово «надежно» я пропустил умышленно…
Как перенести длинную строку?
Совет по поводу экранирующего символа ^ имеет еще одно применение: перенос строк. Я (как и многие из вас, наверное) люблю, чтобы любой исходный текст, который я пишу, выглядел красиво – даже *.bat-файлы. Одним из обязательных условий красоты и удобочитаемости кода для меня является его ширина: все строки должны умещаться в 78 столбцов. Можно поспорить по поводу числа 78, но в одном я непреклонен – ограничение на ширину текста кода должно быть, иначе это не код, а макароны.
Так вот долгое время *.bat-файлы портили мне жизнь тем, что иногда приходилось писать длинную строку – например, вызов какой-нибудь другой программы с кучей опций, и я не знал, что с этим делать. Происходило это нечасто, но всегда было неприятно. Но, к счастью, моя жизнь изменилась с тех пор, как я открыл для себя Супер-Символ ^:
packagebin.exe --recursive-search=yes --files-mask=exe,dll,pdb,obj ^ --archive-type=zip --archive-level=max --deliver-method=ftp ^ --deliver-target=ftp://ftp.site.com
Помните лишь, что чудо-символ должен быть последним в строке – скажите «Нет!» концевым пробелам.
Как определить имя каталога, в котором находится запущенный командный файл?
Иногда сценарию надо знать полный путь к себе самому и/или к каталогу, в котором он находится. Это может понадобиться по разным причинам. Например, он должен достать из системы контроля версий исходники в каталог/src рядом с собой. Или, запускаются тесты из каталога/tests, и перед их запуском надо добавить каталог/bin в переменную PATH.
Можно, конечно, рассчитывать на то, что командный файл был вызван из того же каталога, где он находится, и тогда в качестве вышеупомянутогоможно использовать переменную окружения %CD% — полный путь к текущему каталогу. Однако любые допущения в нашем деле недопустимы (хороший каламбур, однако!). Поэтому приведу более надежное решение.
Прежде всего, вспоминаем, что переменная %0 в bat-файле соответствует нулевому аргументу командной строки, т.е. имени самого файла. После этого читаем скудную документацию для команды call:
call /?
и обнаруживаем, что при использовании нумерованных переменных %0-%9 можно использовать некоторые модификаторы:
%~1 — разворачивает %1, удаляя кавычки («)
%~f1 — разворачивает %1 в полный квалифицированный путь
%~d1 — разворачивает %1 в букву диска
%~p1 — разворачивает %1 в путь
%~n1 — разворачивает %1 в имя файла
%~x1 — разворачивает %1 в расширение файла
%~s1 — развернутый путь будет содержать только короткие имена
%~a1 — разворачивает %1 в атрибуты файла
%~t1 — разворачивает %1 в дату/время создания файла
%~z1 — разворачивает %1 в размер файла
%~$PATH:1 — Ищет в каталогах, перечисленных в переменной среды PATH, и разворачивает %1 в полное квалифицированное имя первого совпадения. Если имя переменной среды не определено, или если файл не найден, этот модификатор вернет пустую строку и, более того, модификаторы можно объединять для получения сложных результатов:
%~dp1 - разворачивает %1 в букву диска и путь %~nx1 - разворачивает %1 в имя файла с расширением %~dp$PATH:1 – ищет %1 в каталогах, перечисленных в переменной среды PATH, и разворачивает в букву диска и путь к первому найденному файлу. %~ftza1 - разворачивает %1 в строку, подобную DIR
Таким образом, правильным будет использовать в качестве тега сочетание %~dp0, которое будет раскрыто в полный путь к каталогу, где находится сценарий. Например,
"%~dp0\packagebin.exe" --recursive-search=yes --files-mask=exe,dll,pdb,obj ^ --archive-type=zip --archive-level=max --deliver-method=ftp ^ --deliver-target=ftp://ftp.site.com --deliver-source="%~dp0\bin"
Обратите внимание на использование кавычек – потенциально каталог может иметь в своем пути пробел. Кавычки избавят от проблем в этом случае.
Опасайтесь бездумного применения команды cd %~dp0 без проверки результата выполнения. Теоретически, эта команда должна сменить текущий каталог на каталог, в котором расположен командный файл. Как правило, это работает. Однако возможны неожиданности. Однажды был написан простой командный сценарий, задача которого была просто удалить все каталоги рядом с собой. В «свою» директорию он переходил как раз через cd %~dp0. Все было проверено на локальной машине – работало замечательно. После этого сценарий был помещен на файл-сервер, где ему и полагалось быть. Я зашел с помощью Far в сетевой каталог, и для контрольной проверки решил запустить файл еще раз. Дальнейшее словно в тумане. cmd.exe правильно определил местонахождение bat-файла: \\servername\sharename\directory. Однако при попытке сделать туда cd, он сказал, что UNC-пути в качестве текущих каталогов не поддерживаются и лучше он сменит текущий каталог на C:\WINDOWS… Это было действительно мудрое решение… Часть сценария, отвечавшая за удаление всех каталогов, сработала отлично – хорошо, что я успел вовремя остановить это безумие.
В тот день я узнал, что такое System Restore…
Как получить короткое (8.3) имя файла?
«А зачем? – спросите вы – Ведь мы живем в мире Интернета, Web-сервисов и NTFS с длинными именами файлов». Это действительно так, но иногда встречаются программы, которые отчаянно сопротивляются прогрессу, и в частности, не любят имен файлов и полных путей с пробелами. Одной из таких программ, кстати, является утилита build.exe из Windows DDK… В таких ситуациях спасает использование короткого, «беспробельного» DOS-имени для файла.
Доступ к файлу по короткому имени может быть не всегда возможен. На файловой системе NTFS создание коротких псевдонимов для файлов может быть отключено путем установки в единицу значения «NtfsDisable8dot3NameCreation» в ключе реестра «HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\FileSystem».
Итак, все же (в предположении, что надругательства над NTFS не было) – как? Внимательный читатель должен был заметить в предыдущем разделе, что при обращении к переменным %0 — %9 можно использовать префикс (расширенный путь будет содержать только короткие имена)
%~s1
который нам как раз мог бы помочь. Но есть засада – все эти полезные префиксы нельзя использовать с произвольной переменной окружения, а присваивание переменным %0 — %9 не поддерживается. К счастью, описываемые префиксы можно еще использовать с переменными цикла for, и это дает нам способ достичь требуемого результата. Например, вот так можно получить 8.3-путь к “Program Files”:
for /d %%i in ("%PROGRAMFILES%") do (
set PROGRAMFILESSHORT=%%~si )
echo 8.3-имя для каталога "%PROGRAMFILES%" -^> "%PROGRAMFILESSHORT%"
Этот и другие модификаторы можно использовать и с любой другой формой цикла for, подробнее о которых можно узнать из (см. также статью [1]):
for /?
Как перенаправить стандартный вывод в файл?
Плоха та короткая программа, которая не стремится стать большой. К сожалению, это правило применимо и к командным файлам Windows тоже – иногда bat-файлы вырастают до довольно больших размеров. Если при этом результат выполняемых команд должен журналироваться, то все становится совсем плохо – почти каждая строка имеет хвостик типа
echo Cleaning up the target directory >>%LOGFILE% ...
echo The target directory has been cleaned >>%LOGFILE%
Гораздо проще было бы перенаправить стандартный вывод в файл, чтобы все команды echo и вообще, все, что выводится на экран, автоматически попадали в журнальный файл. Сделать это можно следующим образом (рассмотрим на знакомом примере генерации HTML-файла):
@echo off set OUTPUT=out.html if "%STDOUT_REDIRECTED%" == "" ( set STDOUT_REDIRECTED=yes cmd.exe /c %0 %* >%OUTPUT% exit /b %ERRORLEVEL% ) echo ^<html^> echo ^<head^> echo ^<title^>This is a greeting page^</title^> echo ^</head^> echo ^<body^> echo Hello World! echo ^</body^> echo ^</html^>
Здесь делается то же, что и раньше, но с перенаправлением стандартного вывода в файл out.html. Делается это простым способом – перезапуском сценарием самого себя. Сначала проверяется, не установлена ли переменная окружения STDOUT_REDIRECTED. Если она установлена, значит, сценарий уже перезапущен с перенаправленным выводом и можно просто продолжить работу. Если же переменная не установлена, то мы ее устанавливаем и перезапускаем скрипт (cmd.exe /c %0) с таким же набором параметров, что и исходная команда (%*) и перенаправленным в файл стандартным выводом (>%OUTPUT%). После завершения выполнения «перенаправленной» команды выходим.
Такое «единовременное» перенаправление имеет и еще один неочевидный плюс: файл открывается и закрывается только один раз, и всем командам и дочерним процессам передается дескриптор уже открытого файла. Во-первых, это чуть-чуть улучшит производительность (жизнь удалась – сроду бы не подумал, что буду когда-нибудь писать о производительности в bat-файлах). Во-вторых, это поможет избежать проблемы с невозможностью открыть файл для записи. Такое может случиться, если после выполнения одной из команд останется «висеть» какой-нибудь процесс. Он будет держать дескриптор интересующего нас файла и перенаправление вывода в этот файл для всех последующих команд провалится. Проблема может показаться надуманной, но однажды она украла у меня 2 часа жизни…
Как сложить два числа?
Краткий ответ – смотри:
set /?
Длинный ответ таков. В bat-файлах можно производить довольно-таки продвинутые вычисления – продвинутые не в сравнении с другими языками, а в сравнении с отсутствием возможности что-либо вычислить вообще. Вычисление осуществляется командой set, если она выполняется с ключом /a. Поддерживается практически полный набор операторов языка C, включая шестнадцатеричный модификатор 0x. Переменные окружения в выражении не обязательно заключать в знаки процента – все, что не является числом, считается переменной. Подробнее – все-таки в man set, тьфу, то есть в set /?. А здесь напоследок – просто несколько примеров.
@echo off
set ARG=1
rem Переменные окружения в выражении не обязательно заключать в %...%
set /a RESULT=ARG + 2
echo %RESULT%
rem Если выражение содержит какие-либо из символов non grata, надо
rem заключить его в кавычки
set /a RESULT="ARG << 2"
echo %RESULT%
rem Шестнадцатеричная арифметика
set /a RESULT=0x1234 + 0x6786
echo %RESULT%
rem И многое-многое другое...
А можно создать в bat-файле функцию?
Да, можно. Более того, иногда даже нужно. Правда, функциями это можно назвать условно. Есть особый синтаксис команды call, который позволяет перейти на метку в этом же bat-файле с запоминанием места, откуда был произведен этот вызов:
call :метка аргументы
Возврат из функции производится командой:
exit /b [опциональный код возврата]
Ключ /b здесь очень важен: без него будет произведен выход не из функции, а из сценария вообще. За подробностями обращайтесь к:
call /?
exit /?
Что интересно, команда call с таким синтаксисом поддерживает рекурсивные вызовы с автоматическим созданием нового фрейма для переменных аргументов %0-%9. Иногда это может быть полезным. Вот классический пример рекурсивного подсчета факториала на командном языке:
@echo off
call :factorial %1
echo %RESULT% exit
rem Функция для подсчета значения факториала
rem Вход: %1 Число, для которого необходимо подсчитать факториал
rem Выход: %RESULT% Значение факториала
:factorial
if %1 == 0 (
set RESULT=1 exit /b )
if %1 == 1 (
set RESULT=1 exit /b )
set /a PARAM=%1 - 1
call :factorial %PARAM%
set /a RESULT=%1 * %RESULT% exit /b
Пример работы:
> factorial.bat 10
3628800
Как можно избежать использования goto?
Любой хоть сколько-то осмысленный *.bat-файл длиной больше 50 строк является ярким лозунгом в поддержку работы Дейкстры [3]. Мешанина из переходов вперед и назад действительно является кодом «только для записи». Можно ли что-то предпринять по этому поводу?
На самом деле можно. Как правило, большинство меток и переходов используются для организации ветвлений при проверке условий, т.е. банальных if-then-else блоков. В оригинале, bat-язык поддерживал только одну команду в блоке then, что автоматически приводило к идиомам вида:
if condition goto :THEN
rem Команды ветки ‘else’
rem ...
goto IF_END
:THEN
rem Команды ветки ‘then’
rem ...
:IF_END
Но к счастью, командный интерпретатор cmd.exe современных ОС Windows 2000 и старше поддерживает блоки команд в конструкциях ветвления, что устраняет необходимость применения меток. Блоки команд заключаются в круглые скобки. Выглядит это так (имитируя C/C++ indentation style):
if condition (
rem Команды ветки ‘then’ rem ... ) else (
rem Команды ветки ‘else’ rem ... )
Конкретный пример использования:
@echo off
set BUILDMODE=%1
if "%BUILDMODE%" == "" (
echo FAIL: Аргумент является обязательным ^(--debug, --release^) exit /b 1 )
rem Удаляем из аргумента все дефисы для упрощения обработки
set BUILDMODE=%BUILDMODE:-=%
if "%BUILDMODE%" == "debug" (
echo INFO: Устанавливаем debug-режим окружения
set CCFLAGS=/Od /MDd /Z7 ) else (
echo INFO: Устанавливаем release-режим окружения
set CCFLAGS=/O2 /MD )
На мой взгляд, с этим уже вполне можно жить. Но, как всегда, жизнь не так проста, как кажется. Есть одна проблема. Переменные, использующиеся в блоках then и else, раскрываются перед началом выполнения этих блоков, а не в процессе выполнения. В приведенном примере это не вызывает никаких проблем, однако в следующем вызовет:
if "%BUILDMODE%" == "debug" (
echo INFO: Устанавливаем debug-режим окружения set OPTFLAGS=/Od
set CCFLAGS=%OPTFLAGS% /MDd /Z7 ) else (
echo INFO: Устанавливаем release-режим окружения set OPTFLAGS=/O2
set CCFLAGS=%OPTFLAGS% /MD )
Загвоздка в том, что в обоих блоках подстановка переменной OPTFLAGS произойдет до того, как она будет изменена в процессе выполнения этого блока. Соответственно, в CCFLAGS будет подставлено то значение, которое OPTFLAGS имела на момент начала выполнения данного if-блока.
Решается эта проблема путем использования отложенного раскрытия переменных. Переменные, заключенные в !…! вместо %…%, будут раскрыты в их значения только в момент непосредственного использования. Данный режим по умолчанию отключен. Включить его можно либо использованием ключа /V:ON при вызове cmd.exe, либо использованием команды
setlocal enabledelayedexpansion
в тексте самого bat-файла. Второй способ мне представляется более удобным – не очень здорово требовать от кого-то запуска твоего сценария с определенным параметром.
С учетом сказанного предыдущий «неправильный» пример может быть исправлен так:
if "%BUILDMODE%" == "debug" (
echo INFO: Setting up debug mode environment set OPTFLAGS=/Od
set CCFLAGS=!OPTFLAGS! /MDd /Z7 ) else (
echo INFO: Setting up release mode environment set OPTFLAGS=/O2
set CCFLAGS=!OPTFLAGS! /MD )
Вот теперь это почти полноценный if-then-else блок. Почти, потому что если в одной из команд echo у вас встретится закрывающая круглая скобка, то вам необходимо заэкранировать ее символом ^, иначе синтаксический анализатор путается…
Но в любом случае, это гораздо лучше безумного количества меток и переходов.
Как обработать текстовый файл?
Иногда в командном файле необходимо получить доступ к содержимому некоторого текстового файла и некоторым образом это содержимое обработать. Например, прочитать файл настроек программы.
Для привнесения еще большей конкретики в процесс изучения зададимся целью прочитать файл с настройками следующего содержания:
buildmode=release
compiler=cl.exe
arch=x86
Ничего сверхъестественного – простой key=value формат с возможностью вставки Unix-style комментариев. Помочь в чтении и обработке этого файла нам сможет команда for. Ее дополнительные опции позволяют задать и разделители, и символ начала комментария, и кое-что еще. Вот командный файл, который выполняет поставленную задачу:
@echo off
rem Читаем настройки из файла settings.txt, который должен располагаться в
rem том же каталоге, что и bat-файл. Если не удалось распарсить настройки -
rem выходим с ненулевым кодом возврата.
call :read_settings %~dp0\settings.txt || exit /b 1
rem Прочитанные настройки:
echo Build mode : %BUILDMODE%
echo Compiler : %COMPILER%
echo Architecture: %ARCH%
rem Выход из сценария. Дальше - только функции. exit /b 0
rem Функция для чтения настроек из файла.
rem Вход: %1 - Имя файла с настройками
:read_settings
set SETTINGSFILE=%1
rem Проверка существования файла
if not exist %SETTINGSFILE% (
echo FAIL: Файл с настройками отсутствует exit /b 1 )
rem Обработка файла c настройками
rem Здесь: eol=# указывает на то, что содержимое строки начиная с символа #
rem и до ее конца может быть пропущено как комментарий.
rem delims== указывает, что разделителем значений является символ =
rem tokens=1,2 приводит к тому, что в переменную %%i будет занесен первый
rem токен, а в %%j - второй.
for /f "eol=# delims== tokens=1,2" %%i in (%SETTINGSFILE%) do (
rem В переменной i - ключ
rem В переменной j - значение
rem Мы транслируем это в переменные окружения set %%i=%%j ) exit /b 0
Обильные комментарии должны помочь легко разобраться, что к чему. За подробностями, как обычно, отошлю к:
for /?
Кстати, возможности команды for не ограничиваются чтением из файла. Возможно также чтение вывода другой команды. Например, так:
@echo off for /f "tokens=* usebackq" %%i in (`cmd.exe /c ver`) do ( set VERSION=%%i ) echo %VERSION%
Особенно меня умиляет наличие опции “usebackq”, которая делает синтаксис отдаленно похожим на юниксовый. И в стенах царства Билла есть граждане, скучающие по /bin/sh и пытающиеся хоть как-то скрасить существование свое и окружающих. Следующий совет это также косвенно подтверждает.
Что это за упомянутые ранее операторы объединения команд?
Это операторы &, && и ||. Они практически совсем не освещены в документации, но полезны в повседневности. Они позволяют объединять несколько команд в одну, т.е. примерно так:
command1 & command2
command1 && command2
command1 || command2
Форма этих операторов весьма соответствует их содержанию. В случае, пожалуй, наименее полезного оператора & вторая команда будет просто выполнена после первой, т.е. это равносильно простой записи:
command1
command2
Оператор && гарантирует, что вторая команда будет выполнена только, если первая была выполнена успешно, т.е. с нулевым кодом возврата (он же %errorlevel%). Такие конструкции очень популярны в мире shell-сценариев Unix. Например:
cd sources && make clean
Я был приятно удивлен, узнав, что cmd.exe тоже умеет выполнять такие конструкции. Это безопаснее и правильнее, нежели простое последовательное выполнение этих команд, и короче и проще, чем строгая проверка и обработка кодов возврата. Очень удобно при написании на скорую руку. Не менее полезен иногда и оператор ||. Суть его тоже логична – выполнить вторую команду, если первая дала сбой. Часто встречается в таких идиомах:
cd sources || exit 1
Если перейти в каталог sources не удастся, то будет произведен выход с кодом ошибки 1. Если же первая команда отработает нормально, то вторая выполнена не будет. Например, такая простейшая защита помогла бы в случае с cd по UNC-адресу, описанному ранее.
Можно ли написать на bat-языке серьезную программу?
Пожалуй, нет. Серьезная программа должна все-таки выглядеть серьезно. А все написанное на командном языке Windows таковым назвать можно лишь с о-о-о-чень большой натяжкой. Так что для решения более сложных задач автоматизации лучше все-таки взять что-нибудь более функциональное:
- Perl
- Python
- Ruby
- JScript / VBScript
Последние, кстати, присутствуют в Windows 2000/XP по умолчанию (с некоторыми функциональными различиями) и в целом могут считаться заменой *.bat языку. Однако сдается мне, что *.bat-файлы проживут еще очень долго.
Как проверить, указан ли определенный аргумент в bat-файле?
Проверить наличие определенного параметра в bat-файле можно оператором if [%1]==[] goto, пример:
@echo off
if [%1]==[] goto usage @echo Это не выполнится, если параметр %1 указан @echo Done.goto :eof
:usage @echo Usage: %0 ^<EnvironmentName^> exit /B 1
Как можно отменить (экранировать) действие специальных символов (< и >)?
Это можно сделать с помощью символа ^ (см. предыдущий пример).
Автор: Алексей Александров. Источник: RSDN Magazine #2-2005
[Ссылки]
1. Применение команды for в bat-файлах (technet.microsoft).
2. DOS Command Index site:earthlink.net.
3. О вреде оператора goto site:vspu.ac.ru.
В мире информационных технологий возможность автоматизации рутинных задач является мощным инструментом повышения эффективности. Один из способов достижения этой цели – использование BAT файлов, которые предоставляют пользователям удобный способ выполнения команд в терминале без вмешательства человека. Независимо от того, работаете ли вы с большими проектами или просто хотите упростить повседневные задачи, внедрение автоматизации с помощью BAT файлов может существенно сэкономить ваше время.
BAT файлы, широко используемые для автоматического выполнения команд в среде операционной системы Windows, позволяют автоматизировать процессы, упрощая взаимодействие с командной строкой. Они являются текстовыми документами, содержащими последовательность команд, которые могут быть запущены одно за другим. Понимание того, как создать и использовать такие файлы, открывает огромные возможности для их применения в различных аспектах работы с компьютером.
Создание BAT файлов включает в себя написание инструкций с использованием встроенных команд для управления системой. Это может включать в себя инициализацию системных процессов, создание резервных копий данных, управление файлами и многими другими операциями. Простой, но мощный синтаксис этих файлов позволяет комплексно подходить к выполнению задач и упрощает их повторное использование. В результате, знание о том, как их создать и использовать, становится ценным навыком в арсенале любого IT-специалиста.
Понимание CMD файлов
В операционной системе Windows используется специальный вид текстового документа, который позволяет автоматизировать выполнение задач. Это средство помогает определить последовательность команд для выполнения желаемых действий. Управление процессами через такой текстовый документ делает рабочие процессы более упорядоченными и эффективными, минимизируя количество ручных действий.
Файлы с расширением .bat представляют собой набор инструкций, которые запускаются средой командной строки. Этот документ позволяет вам составлять и исполнять различные скрипты, включая запуск приложений, управление файлами и изменением их атрибутов. Каждый текстовый документ этого типа содержит множество команд, которые выполняются одна за другой после вызова.
Среди основных преимуществ таких документов – простота использования и отсутствие необходимости в дополнительных программных инструментах. Они эффективны для выполнения рутинных задач, таких как автоматическое копирование файлов или настройка системного окружения, что крайне удобно для системных администраторов и продвинутых пользователей.
Важно также понимать, что такие текстовые файлы могут быть мощным инструментом, но при этом их использование требует осторожности. Неправильная настройка или ошибка в команде могут привести к непредвиденным последствиям, таким как потеря данных или сбои в работе системы. Используя командные инструкции, рекомендуется всегда заранее тестировать их в безопасной среде.
Основы языкового синтаксиса
Языковой синтаксис командных файлов значительно упрощает автоматизацию задач. Понимание базовых элементов синтаксиса позволяет эффективно использовать командную строку для управления операционной системой и выполнения различных операций. Знание основ помогает в создании более сложных скриптов и решении разноcложных задач.
Наиболее популярный формат таких скриптов – это .bat файлы. Они состоят из набора команд, которые выполняются последовательно. Каждая команда выполняет определенное действие, от простого копирования файлов до тонкой настройки системных параметров. Важно понимать, что строка команд в таких файлах – это единица выполнения. Главная цель заключается в том, чтобы обеспечить точное выполнение всех команд, включенных в последовательность.
Основные конструкции включают объявление переменных и контроль над потоком выполнения. Переменные позволяют хранить значения, которые могут быть изменены дальше в скрипте. К примеру, оператор SET используется для создания переменной, которая может быть использована в скрипте.
Управление потоком выполнения достигается за счет использования условных операторов и циклов. Если, например, необходимо выполнить команду только при соблюдении определенного условия, используется конструкция IF. Циклы FOR позволяют обрабатывать набор данных или выполнять определенные действия для каждого элемента коллекции. Благодаря такой структуре, автоматизация рутинных задач становится проще.
Владение основами языка даёт возможность не только создавать эффективные bat-скрипты, но и устранять ошибки, а также оптимизировать выполнение команд. Это искусство является важным навыком для IT-специалиста, желающего автоматизировать свои повседневные задачи.
Редакторы для создания CMD файлов
Самым простым вариантом является использование стандартного блокнота, который поставляется с Windows. Несмотря на свои ограниченные возможности, он обладает минималистичным интерфейсом, подходящим для внесения небольших изменений. Его главное преимущество в доступности на любой системе Windows и простоте использования.
Для более профессионального подхода стоит обратить внимание на расширенные текстовые редакторы. К примеру, Notepad++ предоставляет богатый функционал: подсветка синтаксиса облегчает восприятие командных строк, а вкладочная структура ускоряет переключение между несколькими открытыми документами. Это значительно упрощает управление сложными скриптами.
Еще один заметный инструмент – Visual Studio Code. Этот редактор, будучи кроссплатформенной средой, обеспечивает не только комфортную работу с командами, но и множество расширений для повышения функциональности. Например, помощь в автодополнении команд позволяет быстрее и точнее писать скрипты.
Выбор редактора зависит от вашего опыта и сложности выполняемых задач. Начинающим пользователям лучше сосредоточиться на простейших инструментах, тогда как опытным специалистам подойдут редакторы с продвинутыми возможностями, которые повышают продуктивность и уменьшают количество ошибок в написании команд. Независимо от выбранного инструмента, ключевой задачей остается эффективное создание корректных и функциональных командных файлов.
Практическое руководство по написанию кода
Изучение основ написания скриптов помогает автоматизировать разнообразные задачи в операционной системе. Если вы хотите научиться пользоваться скриптами формата .bat
, начните с простых командных строк, которые выполняют базовые действия. Это позволит лучше понять, как взаимосвязаны команды и как их применять в различных сценариях.
Перед началом программирования полезно знать, какие команды и их параметры существуют в командной строке. Это позволяет пользователю выстраивать последовательности команд, выполняемые в нужном порядке. Постепенное освоение более сложных скриптов открывает возможности для оптимизации рутинных процессов.
В таблице ниже представлены базовые команды, которые часто используются при написании .bat
файлов и их краткое описание:
Команда | Описание |
---|---|
echo |
|
start |
Запускает новое окно или программу. |
pause |
Останавливает выполнение скрипта до тех пор, пока пользователь не нажмёт клавишу. |
rem |
Добавляет комментарий в код, помогая его структурированию и объяснению. |
for |
Организует цикл, повторяя выполнении набора команд несколько раз. |
Знание и понимание этих элементов позволит лучше управлять и адаптировать скрипт под ваши нужды. Пробуйте экспериментировать, создавая и изменяя скрипты, чтобы развивать свои навыки в программировании и находить оптимальные способы выполнения задач.
Отладка и тестирование CMD файлов
Когда вы завершили процесс программирования вашего bat-скрипта, следующим важным шагом становится его проверка на наличие ошибок и оптимизация рабочих процессов. Эта часть разработки требует особого внимания, так как небольшие ошибки могут существенно повлиять на выполнение команды в системе. Наша цель – обеспечить стабильность и надежность вашей автоматизации, устранив возможные неполадки.
Использование командного интерфейса Windows открывает множество возможностей для детальной отладки. Начните с запуска вашего скрипта в пошаговом режиме, чтобы видеть порядок выполнения каждой команды. Для этого можно использовать команду pause
, что позволит остановить выполнение и проверить текущий статус перед продолжением.
Не забывайте об использовании эмуляторов терминалов, таких как Windows Terminal или аналогичные программы. Эти инструменты предоставляют расширенные возможности для взаимодействия с командной строкой, включая разный уровень подсветки синтаксиса и дополнительные средства мониторинга процессов.
В случае, если ваш скрипт предназначен для запуска на нескольких версиях ОС Windows, убедитесь, что он учтёт возможные различия в командных интерпретаторах и внутреннем функционале. Это позволит избежать несовместимости и обеспечить универсальную производительность вашего кода.
Регулярно выполняйте тестирование в условиях, максимально приближенных к рабочим. Это незаменимый шаг, особенно если ваш скрипт будет использоваться в производственном окружении. Помните, что от качества вашей тестовой базы зависит безопасность и надёжность выполнения вашего скрипта.
Примеры и шаблоны люстрирующие создание
Для более глубокого понимания процесса работы с командными файлами и их кода, полезно изучить примеры и готовые шаблоны. Они помогают увидеть реальное применение языкового синтаксиса и открыть для себя новые возможности. Рассмотрим наборы полезных скриптов, демонстрирующих ключевые аспекты и функции.
- Простейший пример:
Запуск калькулятора и блокнота:
- Откройте текстовый редактор и вставьте строки:
@echo off start calc.exe start notepad.exe
- Сохраните файл с расширением
.bat
.
- Откройте текстовый редактор и вставьте строки:
- Создание резервной копии:
Скрипт для автоматического архивирования папки:
- Откройте редактор и добавьте:
@echo off xcopy C:\исходная_папка D:\резервная_копия /E /I /Y
- Сохраните как
backup.bat
. - Запустите для создания резервной копии.
- Откройте редактор и добавьте:
- Проверка доступности сайтов:
Командный файл для мониторинга веб-сайтов:
- Вставьте следующий код в текстовый файл:
@echo off ping -n 1 www.example.com >nul if errorlevel 1 ( echo Website is down ) else ( echo Website is up )
- Сохраните под именем
check_website.bat
.
- Вставьте следующий код в текстовый файл:
Эти примеры показывают разнообразие задач, которые могут быть автоматизированы. Работая с командными файлами, можно существенно упростить выполнение рутинных операций, повысив эффективность и снизив количество ошибок.
Комментарии