- Overview
- Part 1 – Getting Started
- Part 2 – Variables
- Part 3 – Return Codes
- Part 4 – stdin, stdout, stderr
- Part 5 – If/Then Conditionals
- Part 6 – Loops
- Part 7 – Functions
- Part 8 – Parsing Input
- Part 9 – Logging
- Part 10 – Advanced Tricks
Today we’ll cover variables, which are going to be necessary in any non-trivial batch programs. The syntax for variables can be a bit odd,
so it will help to be able to understand a variable and how it’s being used.
Variable Declaration
DOS does not require declaration of variables. The value of undeclared/uninitialized variables is an empty string, or ""
. Most people like this, as
it reduces the amount of code to write. Personally, I’d like the option to require a variable is declared before it’s used, as this catches
silly bugs like typos in variable names.
Variable Assignment
The SET
command assigns a value to a variable.
SET foo=bar
NOTE: Do not use whitespace between the name and value; SET foo = bar
will not work but SET foo=bar
will work.
The /A
switch supports arthimetic operations during assigments. This is a useful tool if you need to validated that user input is a numerical value.
SET /A four=2+2
4
A common convention is to use lowercase names for your script’s variables. System-wide variables, known as environmental variables, use uppercase names. These environmental describe where to find certain things in your system, such as %TEMP%
which is path for temporary files. DOS is case insensitive, so this convention isn’t enforced but it’s a good idea to make your script’s easier to read and troubleshoot.
WARNING: SET
will always overwrite (clobber) any existing variables. It’s a good idea to verify you aren’t overwriting a system-wide variable when writing a script. A quick ECHO %foo%
will confirm that the variable foo
isn’t an existing variable. For example, it might be tempting to name a variable “temp”, but, that would change the meaning of the widely used “%TEMP%” environmental varible. DOS includes some “dynamic” environmental variables that behave more like commands. These dynamic varibles include %DATE%
, %RANDOM%
, and %CD%
. It would be a bad idea to overwrite these dynamic variables.
Reading the Value of a Variable
In most situations you can read the value of a variable by prefixing and postfixing the variable name with the %
operator. The example below prints the current value of the variable foo
to the console output.
C:\> SET foo=bar
C:\> ECHO %foo%
bar
There are some special situations in which variables do not use this %
syntax. We’ll discuss these special cases later in this series.
Listing Existing Variables
The SET
command with no arguments will list all variables for the current command prompt session. Most of these varaiables will be system-wide environmental variables, like %PATH%
or %TEMP%
.
NOTE: Calling SET
will list all regular (static) variables for the current session. This listing excludes the dynamic environmental variables like %DATE%
or %CD%
. You can list these dynamic variables by viewing the end of the help text for SET, invoked by calling SET /?
Variable Scope (Global vs Local)
By default, variables are global to your entire command prompt session. Call the SETLOCAL
command to make variables local to the scope of your script. After calling SETLOCAL
, any variable assignments revert upon calling ENDLOCAL
, calling EXIT
, or when execution reaches the end of file (EOF) in your script.
This example demonstrates changing an existing variable named foo
within a script named HelloWorld.cmd
. The shell restores the original value of %foo%
when HelloWorld.cmd
exits.
A real life example might be a script that modifies the system-wide %PATH%
environmental variable, which is the list of directories to search for a command when executing a command.
Special Variables
There are a few special situations where variables work a bit differently. The arguments passed on the command line to your script are also variables, but, don’t use the %var%
syntax. Rather, you read each argument using a single %
with a digit 0-9, representing the ordinal position of the argument.
You’ll see this same style used later with a hack to create functions/subroutines in batch scripts.
There is also a variable syntax using !
, like !var!
. This is a special type of situation called delayed expansion.
You’ll learn more about delayed expansion in when we discuss conditionals (if/then) and looping.
Command Line Arguments to Your Script
You can read the command line arguments passed to your script using a special syntax. The syntax is a single %
character followed by the ordinal position of the argument from 0
– 9
. The zero ordinal argument is the name of the batch file itself. So the variable %0
in our script HelloWorld.cmd
will be “HelloWorld.cmd”.
The command line argument variables are
* %0
: the name of the script/program as called on the command line; always a non-empty value
* %1
: the first command line argument; empty if no arguments were provided
* %2
: the second command line argument; empty if a second argument wasn’t provided
* …:
* %9
: the ninth command line argument
NOTE: DOS does support more than 9 command line arguments, however, you cannot directly read the 10th argument of higher. This is because the special variable syntax doesn’t recognize %10
or higher. In fact, the shell reads %10
as postfix the %0
command line argument with the string “0”. Use the SHIFT
command to pop the first argument from the list of arguments, which “shifts” all arguments one place to the left. For example, the the second argument shifts from position %2
to %1
, which then exposes the 10th argument as %9
. You will learn how to process a large number of arguments in a loop later in this series.
Tricks with Command Line Arguments
Command Line Arguments also support some really useful optional syntax to run quasi-macros on command line arguments that are file paths. These macros
are called variable substitution support and can resolve the path, timestamp, or size of file that is a command line argument. The documentation for
this super useful feature is a bit hard to find – run ‘FOR /?’ and page to the end of the output.
%~I
removes quotes from the first command line argument, which is super useful when working with arguments to file paths. You will need to quote any file paths, but, quoting a file path twice will cause a file not found error.
SET myvar=%~I
-
%~fI
is the full path to the folder of the first command line argument -
%~fsI
is the same as above but the extras
option yields the DOS 8.3 short name path to the first command line argument (e.g.,C:\PROGRA~1
is
usually the 8.3 short name variant ofC:\Program Files
). This can be helpful when using third party scripts or programs that don’t handle spaces
in file paths. -
%~dpI
is the full path to the parent folder of the first command line argument. I use this trick in nearly every batch file I write to determine
where the script file itself lives. The syntaxSET parent=%~dp0
will put the path of the folder for the script file in the variable%parent%
. -
%~nxI
is just the file name and file extension of the first command line argument. I also use this trick frequently to determine the
name of the script at runtime. If I need to print messages to the user, I like to prefix the message with the script’s name, like
ECHO %~n0: some message
instead ofECHO some message
. The prefixing helps the end user by knowing the output is
from the script and not another program being called by the script. It may sound silly until you spend hours trying to track down
an obtuse error message generated by a script. This is a nice piece of polish
I picked up from the Unix/Linux world.
Some Final Polish
I always include these commands at the top of my batch scripts:
SETLOCAL ENABLEEXTENSIONS
SET me=%~n0
SET parent=%~dp0
The SETLOCAL
command ensures that I don’t clobber any existing variables after my script exits. The ENABLEEXTENSIONS
argument turns on a very
helpful feature called command processor extensions. Trust me, you want command processor extensions. I also store the name of the script
(without the file extension) in a variable named %me%
; I use this variable as the prefix to any printed messages (e.g. ECHO %me%: some message
).
I also store the parent path to the script in a variable named %parent%
. I use this variable to make fully qualified filepaths to any
other files in the same directory as our script.
<< Part 1 – Getting Started
Part 3 – Return Codes >>
Environment variables are a collection of dynamic named values that are saved on the system and utilized by programs that are running in shells or subshells on Linux and Unix-based systems. An environment variable is, to put it simply, a variable with a name and a corresponding value.
You can alter the system’s operation and the actions of its programs by using environment variables. For instance, the environment variable may keep track of the default text editor or browser, the location of executable files, or the keyboard layout and system locale.
Environment Variables and Shell Variables
Variables are formatted as follows:
KEY=value KEY="Some other value" KEY=value1:value2
- When naming the variables, the case matters. By convention, environment variables’ names must be in UPPER CASE.
- When assigning values to the variable, the colon: the character must be used to separate the values.
- There is no white space around the equals = sign.
The two fundamental groups into which variables can be separated are the environment and the shell.
All child processes and shells that are launched inherit any environment variables that are system-wide and available.
Only the current shell instance is affected by shell variables. There are specific internal shell variables for each shell, including zsh and bash.
In Linux, a number of commands are available to list and set environment variables, including the following:
- Using the command env, you can execute a different program in a unique environment without changing the one that is already in use. If it is used without an argument, a list of the current environment variables will be printed.
- The command printenv prints every environment variable or just the ones that are supplied.
- Using the set command, shell variables can be set or unset. Without an argument, it will display a list of all variables, including shell and environment variables as well as shell functions.
- Delete shell and environment variables with the unset command.
- Environment variables are set with the command export.
Printing Environment Variables
In order to display environment variables printenv is the most used command that serves the purpose. Only that variable’s value is displayed, if its name is supplied as an argument to the command. printenv prints a list of all environment variables, one variable per line, if no argument is given.
For instance, you would execute: to display the value of the HOME environment variable.
For instance, you would execute: to display the value of the PATH environment variable.
For instance, running the printenv or env command without any arguments will display a list of all environment variables:
Some of the most prevalent environmental variables are listed below:
- USER — The user who is currently logged in.
- HOME — The current user’s home directory.
- EDITOR — The file editor that will be used by default. When you type edit in your terminal, this is the editor that will be used.
- SHELL — The current user’s shell path, such as bash or zsh.
- LOGNAME — The current user’s name.
- PATH — A list of folders that will be searched when commands are executed. When you run a command, the system will scan those directories in the order listed above and utilize the first executable found.
- LANG — The current locale configuration.
- TERM — Terminal emulation at the moment.
- MAIL — The location of the current user’s email.
Only the environment variables are printed using the printenv and env commands.
Other Methods to List Linux Environment Variables
The following command will display shell and environment variables using the built-in shell utility declare:-
declare
Using the set command, you may retrieve a list of every variable, including environment, shell variables, and shell functions:
set
You should most likely pipe the output to the less command because the command will output a lengthy list of all variables.
Persistent Environment Variables
Environment variables must be defined in the bash configuration files if you want them to be persistent. In most Linux systems, when a new session is launched, environment variables are read from the following files:
- The system-wide environment variables are made to be set using the /etc/environment file. Following is the format for the same:
$ FOO=bar $ VAR _A="GeeksforGeeks"
- The variables set in this file are loaded in the /etc/profile each time a bash login shell is used. Declare environment variables in this file using the export command:
$ export JAVA_HOME="/path/to/java/home" $ export PATH=$PATH:$JAVA_HOME/bin
- Shell configuration files specific to each user. For instance, if you’re using Bash, you can define the variables in the /.bashrc file:
$ export PATH="$HOME/bin:$PATH"
You can add additional environment variables to the running shell session by using the source command:
$ source ~/.bashrc
Setting Shell and Environment Variables
Using the name VAR_A and the value Welcome, you can easily create a new shell variable by typing:
Creating Shell Variables
Let’s start by setting up a shell variable for the active session. To accomplish this, all we need to do is provide a name and a value. We’ll stick to tradition and set the variable to a simple string while maintaining the variable name in all caps.
Now there is a shell variable. Despite being present in our current session, this variable won’t be shared with any child processes.
In the set output, we can observe this by grepping for our new variable:
By performing the identical thing with printenv, we can confirm that this is not an environmental variable:
There should be no output produced.
Creating Environmental Variables
Let’s now convert the shell variable to an environmental variable. Exporting the variable will allow us to achieve this. The appropriate command to do so is named as follows:
As a result, our variable will now be an environment variable. This can be verified by rechecking our environmental listing with printenv command.
Demoting and Unsetting Variables
We continue to declare our VAR_A variable as an environmental variable. By typing the following, we can turn it back into a shell variable:
However, it is still a shell variable:
The unset command can be used to totally unset a variable, whether it be shell or environmental:
The variable was unset, thus nothing is returned.
Batch Script of Environment Variables
Following is the batch script of environment variables: PATH, HOME, LANG, and SHELL.
Script:
#!/bin/bash echo $PATH echo $HOME echo $LANG echo $SHELL
Output:
Batch manual. Keywords: batch bat shell script scripting windows
LEARN HOW TO BATCH
Table of contents
- What you have to know before we start
- Change your mindset & be patient — Easy is gonna become hard
- The .bat extension
- There are only 2 types: String and Number
- Avoid spaces
- Use
setlocal enabledelayedexpansion
- Script returned value — 0 vs 1
- Avoid blocks as much as possible
- You should organise your script using subroutines
- Getting started
- Basic script example
- Subroutines
- Basic
- Intermediate
- Advanced — Returning multiple values
- String manipulation
- How to
- How to set a variable from a command output?
- How to get the parent folder of the current file?
- Annex
- Special variables
What you have to know before we start
Change your mindset & be patient — Easy is gonna become hard
You’re dealing with some super primitive shit here. The cmd.exe compiler is extremely primitive and what is trivial to do in other language is now gone. This is why I’m writing this document. My mission is to help you swear less at your machine than what I did when I had to learn this horrible piece of shit crap from Microsoft.
The .bat extension
To run a batch script, simply enter the name of your .bat
file in the terminal:
> hello.bat
This executes the scripts defined in the hello.bat
file.
There are only 2 types: String and Number
Forget about booleans, objects, … The following does not set the var_01
to a truthy boolean. Instead, it sets the string value true
.
set var_01=true
Avoid spaces
Batch scripts have a really fucked up unpredictable way of dealing with spaces, so do your best to not use them:
:: Don't do this set hello = World :: Instead, use this set hello=World
Use setlocal enabledelayedexpansion
I MEAN IT, JUST FREAKING USE THIS. Trust me, use this, otherwise, your code will start generating really randomly.
TL;DR
If your script mutates variable, and if those variables are used in IFs, then if you don’t use this set up, the variables will not be set sequentially based on your code execution. You’ll be scratching your heads for hours wondering why your code is not working and you’ll see weird stuff when you echo your variables.
Before delayed expansion
@echo off set hello=world echo %hello%
After delayed expansion
@echo off setlocal enabledelayedexpansion set hello=world echo !hello! endlocal
Explanation
Delayed Expansion will cause variables within a batch file to be expanded at execution time rather than at parse time, this option is turned on with the SETLOCAL EnableDelayedExpansion command.
Variable expansion means replacing a variable (e.g. %windir%) with its value C:\WINDOWS.
Script returned value — 0 vs 1
A successful script returns 0 while an unsuccessful one returns 1. This value is stored inside the global ERRORLEVEL
variable, so you can check it after the script execution to determine whether the script was successful or not.
Avoid blocks as much as possible
The cmd.exe compiler likes reading commands that start and end on the same line. If you think that your code inside an if block is only executed if the condition is true, then be ready for a big surprise. The following will most probably (most probably because is not that predictable, it may actually work) make your code exit:
set do_not_do_this=true if do_not_do_this == false ( echo Mate, do not do this! exit /b 1 ) echo Great mate! You did the right thing
This because the compiler will reads each line inside the block. The following 2 options are more predictable:
set do_not_do_this=true if do_not_do_this == false echo Mate, do not do this! if do_not_do_this == false exit /b 1 echo Great mate! You did the right thing
or
set do_not_do_this=true if do_not_do_this == false (goto :ok) else (goto :notok) :ok echo Great mate! You did the right thing goto :EOF :notok echo Mate, do not do this! exit /b 1
You should organise your script using subroutines
Batch is so primitive that you will eventually need to use subroutines, so better learn how to structure your script from the beginning of your learning journey. To see how to get started with subroutines, please refer to the Subrountines section.
Getting started
Basic script example
:: This is a comment. :: This is how you prevent the terminal to print the entire set of commands below. @echo off setlocal enabledelayedexpansion :: This is how you get an array of all the arguments. echo %* :: This is how you access any arguments passed to the script. :: A new argument occurs each time there is a new space. echo %1 echo %2 :: Prints the name of the .bat file echo %0 :: This is how to define a variable :: WARNING: Though it looks like we're setting a boolean, that's not the case. Remember, the only 2 :: supported types in batch are numbers and string. The line below assigns the string 'false' to the :: variable hello. set hello=false :: This is how you store arithmetic values. If you don't use the /a flag, the :: arithmetic ops is interpreted as a string. set /a numerator=1+2 :: Reference a expandded variable echo !hello! :: Reference a non-expanded variable echo %hello% :: This is how to do an IF. Notice you need to wrap the %1 between double quotes :: to be able to compare against an empty string to check wether it exists or not. :: This is to cover the use case where %1 does not exist. If we don't do this and %1 :: does not exist, an error similar to: Incorrect syntax if neq "". :: Also, notice the "neq" operator. Something like != does not exist :( if "%1" neq "" ( echo Hoorayyyyy, we have a value. ) else ( echo Oh shit, no value ) :: This is how you do a logical AND. The "&&" or "&" do not exist in batch. :: NOTICE: :: - The use the "==" logical equivalence. You could also use "equ" instead. :: - 'exit /b 1' is how you properly exit the execution. The 1 is optional but recommended. :: This allows other scripts to determine whether this script was successful or not. :: (successful scripts return 0) :: - The pattern <command> & exit /b 1. DO NOT use block with 2 lines (one for the :: echo and one for the exit)instead, as this can have unpredictable results. :: Remember, in batch, coding in one line rules. if "%1" == "" if "%2" == "" echo ERROR: Missing required argument --name. & exit /b 1 :: This is how you do a logical OR. The "||" or "|" do not exist in batch. set or_val=false if "%1" neq "" set or_val=true if "%2" neq "" set or_val=true :: Get into the habit to write if else on a single line. The compiler seems to like this better. if or_val equ true (echo OR is ok) else (echo OR is NOT ok) :: This is how you do a 'for' loop. :: NOTICE: :: - With an the output of a command, wrap it between single quotes (e.g., list of files: dir /b /a-d). :: - The /f option must be used to store items from an array (technically, it stands for files). for /f %%x in ('dir /b /a-d') do echo %%x endlocal exit /b 0
Subroutines
Basic
Batch is so primitive that you will eventually need to use subroutines, so better learn how to structure your script from the beginning of your learning journey.
The following script outputs something similar to this:
> test.bat hello world
CORE ARGS: hello world
MAIN ARGS: world hello
test.bat:
@echo off echo CORE ARGS: %1 %2 :: Notice how you must end with '& exit /b' to make sure the rest of the script is not executed. call :main %2 %1 & exit /b :main :: Notice how you still use the %1 convention to get params echo MAIN ARGS: %1 %2 exit /b
Intermediate
@echo off echo CORE ARGS: %1 %2 call :main %2 %1 & exit /b :main setlocal enabledelayedexpansion echo MAIN ARGS: %1 %2 :: Succeeding routine call :divide 6 2 result if !errorlevel! neq 0 exit /b !errorlevel! echo 6 divided by 2 is equal to %result% :: Failing subroutine call :divide 6 0 result if !errorlevel! neq 0 exit /b !errorlevel! echo 6 divided by 1 is equal to %result% endlocal exit /b :divide setlocal enabledelayedexpansion set /a numerator=%1 set /a denominator=%2 if "!denominator!" == "0" echo ERROR - Can't devide by 0 & exit /b 1 set /a result=!numerator!/!denominator! :: NOTICE: :: - The pattern used to set the returning result: set %3=%result% :: Notice that we did not use set %3=!result!. I have no clue why, but you can :: only use %...% when setting the return value. Setting up %3 is not the best :: practice though. Refer to the next section for a more advanced example. :: - The pattern used to maintain the result value from the setlocal scope while :: at the same time setting it to %3. If you had seperated the 'endlocal' and :: 'endlocal' in 2 lines, the value stored in result would had been lost. endlocal & set %3=%result% exit /b
Advanced — Returning multiple values
The previous example demonstrated how to return a value by explicitly setting %3
. However, this can create problem. Take for example the following sample:
call :my_routine %1 %2 result echo %result% exit /b
Setting %3
in :my_routine
only works if it is 100% garanteed that both %1
and %2
exist, because if, for example, %2
is not set, then as far as :my_routine
is concerned, result
is similar to %2
, not %3
. In that case, when :my_routine
sets %3
, it does not set result
.
A better solution is to return an explicit variable as follow:
call :my_routine %1 %2 echo %result% exit /b :my_routine setlocal enabledelayedexpansion :: do stuff set example=hello world endlocal & set result=%example% exit /b
It is also trivial to return many results:
call :my_routine %1 %2 echo %result_01% echo %result_02% exit /b :my_routine setlocal enabledelayedexpansion :: do stuff set example_01=hello world endlocal & set result_01=%example_01% & set result_02=What's up exit /b
String manipulation
set sample=hello world :: Getting a sub-string :: this outputs hell echo %sample:~0,4% :: this outputs world echo %sample:~6,200% :: this outputs hello wor echo %sample:~0,-2%
How to
How to set a variable from a command output?
setlocal enabledelayedexpansion :: This exe is IIS 7.0 set appCmd="!WINDIR!\System32\inetsrv\appcmd.exe" set website_name=demo_01 set website_status=Unknown for /f %%x in ('!appCmd! list site !website_name! /text:state') do set website_status=%%x echo The status of the website !website_name! is: !website_status! endlocal
How to get the parent folder of the current file?
To refresh your mind:
:: Current working directory from where the script is invoked echo %cd% :: Path of this file relative to %cd% echo %0 :: Absolute path to this file echo %cd%\%0
Annex
Special variables
Var | Description |
---|---|
cd |
Current directory where the .bat file is being called (not the directory where the file is). |
WINDIR |
Location of the Windows folder with all its libraries and utils. |
SystemDrive |
This is the drive letter that contains the Windows OS (e.g., C: ) |
In scripts, you’ll use variables to store values as you perform
various types of operations. Unlike most programming languages, you cannot
declare a variable in a command-line script without simultaneously assigning it
a value. This makes a certain amount of sense because from a practical point of
view, there’s no reason to have a variable that contains nothing. The sections
that follow discuss key concepts for working with variables, including
-
Variable names
-
Variable values
-
Variable substitution
-
Variable scope
Naming
Variables
The command shell tracks variable names in the case you use
but doesn’t care about the case when you are working with the variable. This
means variable names aren’t case-sensitive but are case-aware. Beyond this, very
few restrictions apply to variable names and you can use just about any
combination of letters, numbers, and characters to form the variable name. In
fact, all the following variable names are technically valid:
2six
85
!
?
But why in the world you’d want to use such horrendous variable
names is beyond me. With that said, how should you name your variables? Well,
the most important rule to keep in mind is that variable names should be
descriptive. Use names such as
System-name
CurrentStats
mergetotal
Net_Address
These descriptive variable names are helpful when you or someone
else needs to modify the script. And notice that there are many ways to create
multiple- word variable names. Although you are free to use whatever style you
like, most programmers format multiword variable names with a lowercase initial
letter on the first word and uppercase initial letter on each subsequent word.
Why? The reason is simple: this is a standard naming convention. Following this
convention, the variable names used previously are created as
systemName
currentStats
mergeTotal
netAddress
Note |
Keep in mind that the command shell doesn’t care about the |
Setting Variable
Values
As discussed previously, you define new variables using the
following syntax:
set variable_name=variable_value
where variable_name is the variable name and
variable_value is its related value. Spaces are valid in
both names and values. So only use spaces around the equal sign (=) if you want
the name and/or the value to include these spaces.
Unlike many programming languages, the command shell doesn’t
differentiate between various data types. All variables are stored as character
strings. This is true even when you set the variable value to a number. Thus,
the following values are stored as strings:
Current status:
311
"Error!"
12.75
using commands such as:
set varA=Current status:
set varB=311
set varC="Error!"
set varD=12.75
Don’t forget that some characters are reserved in the command
line, including @ < > & | ^. Before you use these characters, you must
escape them with the caret symbol (^) as discussed in Chapter 2, “Getting the Most from the
Command Line”—no matter where they occur in the variable value. For example, to
set these literal string values:
2 & 3 = 5
2^3
you must set the variable value as follows:
2 ^& 3 = 5
2^^3
using statements such as
set example1=2 ^& 3 = 5
set example3=2^^3
Note |
An odd thing happens if you try to echo the example values. |
Substituting
Variable Values
Variables wouldn’t be very useful if the only way you could
access them was with the SET command. Fortunately, you can access variable
values in other ways. One of these ways is to use variable substitution to
compare a variable name with its actual value. You saw this type of substitution
at work in the following line from a previous example in this chapter:
if "%ERRORLEVEL%"=="2" echo "An error occurred!"
Here, you are determining whether the value of the errorlevel environment variable is equal to 2 and, if it is,
you display text stating that an error occurred. The percent signs surrounding
the variable name tell the command shell you are referencing a variable. Without
these percent signs, Windows would perform a literal comparison of “ERRORLEVEL”
and “2”. Note also the use of quotation marks in the example. The quotation
marks ensure an exact comparison of string values.
Another way to use substitution is to replace a variable name with
its actual value. For example, you might want to create a script that can be run
on different computers, so rather than hard-coding the path to the system root
directory as C:\Windows, you could use the environment variable systemroot, which references the system root of the
particular computer being accessed. With this in mind, you use the following
line of code in your script:
cd %SYSTEMROOT%\System32
instead of this line of code:
cd C:\Windows\System32
You can also use variable substitution when you are assigning
variable values, such as
systemPath=%SystemRoot%\System32
Variable substitution can be quite powerful. Consider the code
snippet shown as Listing 3-3.
Listing 3-3: Sample Script Header
@echo off
@if not "%OS%"=="Windows_NT" goto :EXIT
@if "%1"=="" (set INFO=echo && set SEXIT=1) else (set INFO=rem &&
set SEXIT=0)
%INFO% ************************
%INFO% Script: SystemInfo.bat
%INFO% Creation Date: 2/2/2004
%INFO% Last Modified: 3/15/2004
%INFO% Author: William R. Stanek
%INFO% E-mail: williamstanek@aol.com
%INFO% ************************
%INFO% Description: Displays system configuration information
%INFO% Including system name, IP configuration
%INFO% and Windows version.
%INFO% ************************
%INFO% Files: Stores output in c:\current-sys.txt.
%INFO% ************************
@if "%SEXIT%"=="1" goto :EXIT
@title "Configure Scheduling..."
cls
color 07
Listing 3-3 is a
standard header that I use in some of my scripts. The first if statement checks to see what operating system is running.
If it is Windows 2000 or later, meaning Windows 2000, Windows XP, or Windows
Server 2003, the script continues execution. Otherwise a goto
subroutine is called. The second if statement checks
the value of the first argument passed in to the script. If the script is called
with no arguments, instances of %INFO% are replaced with
echo, which writes the script documentation to the output.
If the script is called with one or more arguments, instances of %INFO% are replaced with rem to
designate that the associated lines are comments.
Note |
Don’t worry if you don’t understand the example completely. |
Localizing
Variable Scope
Changes you make to variables in the command shell using set are localized, meaning that they apply only to the
current command shell instance or to command shells started within the current
command shell (nested command shells) and are not available to other system
processes. Further, once you exit the command shell in which variables were
created, the variables no longer exist.
Sometimes you may want to limit the scope of variables even
further than their current command-shell process. To do this, you can create a
local scope within a script that ensures any variable changes are localized to
that specific area within the script. Later, you can end the local scope and
restore the environment to its original settings.
You can mark the start of a local scope within a script using the
SETLOCAL command and then end the local scope with an ENDLOCAL command. Several
events take place when you use these commands. The call to SETLOCAL creates a
snapshot of the environment. Any changes you make within the scope are then
localized and discarded when you call ENDLOCAL. An example using SETLOCAL and
ENDLOCAL follows:
@echo off
set sysCount=0
set deviceCount=0
rem Start localization
setlocal
set sysCount=5
set deviceCount=5
echo Local count: %sysCount% system edits ^& %deviceCount% device
checks
endlocal
echo Count: %sysCount% system edits ^& %deviceCount% device checks
The output of the script is
Local count: 5 system edits & 5 device checks
Count: 0 system edits & 0 device checks
As you can see, local scopes behave much like nested command
shells. As with the nested command shells, you can nest several layers of
localization. And though each layer inherits the environment settings of its
parent, any changes in the nested layer are not reflected in the parent
environment.
Дисклеймер
Мне 12 и я сам в этой теме плохо шарю, т.к. инфы в инете мало. Пж, без хейта.
Что такое батники и с чем их едят
Пакетный файл или в простонародье батник — это файл, который запускает командную сроку или сокращенно cmd, которая построчно интерпретирует команды, записанные в нем. Подробнее смотрите на https://ru.wikipedia.org/wiki/Пакетный_файл.
Первая программа и основные команды
Чтобы сделать батник, нужно сначала создать текстовый файл с именем test и изменить расширение c .txt на .bat. О том, как можно это сделать, читайте здесь: https://remontka.pro/file-extensions. У вас должен появиться файл с такой иконкой:
Нажимаем на него ПРАВОЙ кнопкой мыши. Должно появиться диалоговое окно. Нажмем «Открыть». Должен открыться блокнот, пишем:
@echo off
echo Hello world!
pause
В 1-ой сроке («@echo off») префикс ‘@ ‘ означает, что команда не будет выведена на экран(попробуйте его убрать ), сама же команда (echo) выводит текст следующий за ней(см. строку 2), НО, если подать строку «off», все последующие команды будут действовать так, как будто перед ними стоит префикс ‘@’, «echo on», соответственно, выключает этот режим. Чтобы вывести символ «%», его нужно дублировать, потом поймете почему :-), для вывода пустой строки поставьте «.» после «echo»
В 3-ей строке команда выводит строку «press any key to continue . . .» (если у вас русский язык — «Для продолжения нажмите любую клавишу . . .») и останавливает программу до нажатия любой клавиши.
Наводим красоту
Команда «rem»
не делает ничего и служит комментарием к коду
rem Это самая лучшая прога в мире!!!!!
Код включает русские символы и другие из ascii(например: «╬▓☼», можно скопировать с http://pascalguru.ru/psevdograf.html), иначе ascii символы превратятся в кракозябры:
chcp 65001
Следующий код код работает, как команда «pause», но ничего не выводит на экран и не реагирует на нажатие клавиш(я потом объясню, как это работает).
:m
goto m
А этот — меняет заголовок окна на «name»
title name
Эта команда меняет цвет фона и текста, вместо a и b можно поставить любые шестнадцатеричные цифры(команда не сработает если a = b) см. таблицу ниже. Запись c одной буквой «а» аналогично записи «0a»
color ab
Эта — досрочно завершает программу
exit
Переменные
Создать переменную можно с помощью команды set, синтаксис объявления следующий: P.S. это не совсем переменные, это скорее макросы (для тех к кто не знает C/C++ это именованный кусочек кода, имя которого заменяется на этот кусочек кода)
set a=Hello world
Если после «set» добавить флаг «/a» то:
-
Переменной задастся значение выражения, а не его текст, например:
set a=2+2 > 2+2 set /a a=2+2 > 4
-
Переменной можно присвоить ТОЛЬКО числовое значение
Чтобы обратиться к переменной, нужно окружить ее символами «%» (так %name%), пример кода:
set /a a=%b%+%b%
echo %a%
Подробнее о переменных
Если добавить флаг «/p», то выводиться значение после символа «=», а переменной задается введенное значение(запустите этот код:)
@echo off
set /p a=Enter str
echo %a%
pause
следующий код вырезает строку от символа номер «a» до символа номер «b» НЕ включительно(счет идет с нуля, отрицательные числа — счет с конца от единицы). Если аргумент один, то он присваивается числу «b», а «a» = 0
%str:~a,b%
следующий заменяет подстроки «a» в строке на строки «b»:
%str:a=b%
Циклы и условия
Цикл можно создать с помощью команды «for», синтаксис следующий:
for %%i in (a b c) do (
cmd
)
или такой
for %%i in (a b c) do cmd
(a b c) это список (не обязательно из 3-х элементов) и переменная %%i (нужно ставить символ после процентов, а не между) по очереди проходит по значениям в списке
Если добавить флаг «/l», то переменная в первый раз будет равна «a». К ней каждый раз будет прибавляться «b», пока она не станет больше «c»(тут размер ДОЛЖЕН равняться 3)
запустите этот код, тут все наглядно
@echo off
chcp 65001
echo Начало
for /l %%i in (1 1 10) do echo %%i
echo Конец
pause
Команда if выполняет код, если условие верно (или если поставить not после if, когда НЕ верно), вот операторы сравнения:
P.S. строки нужно брать в кавычки «%str%»==»Hello»
equ(==) |
= |
neq |
≠ |
lss |
< |
leq |
≤ |
gtr |
> |
geq |
≥ |
пример кода:
@echo off
set /p a=Enter number
if a gtr 0 echo positive else\
if a equ 0 echo 0 else echo negative
pause
в 3-ей строке, если «a» > 0 выводиться «положительный»(на английском ), если равен — 0,в 4-ой если меньше — «отрицательный»
символ «\» означает, что команда продолжается на следующей строке
Метки
Создадите файл start.bat в той же папке, где и test.bat, напишите в нем:
test.bat 2 2
Мы запустили батник, НО подали в него аргументы 2 и 2. Чтобы к ним обратиться, нужно написать %n, где «n» — номер аргумента, считая от одного(не от нуля), вот код, считающий сумму первого и второго аргумента (их может быть от нуля до 9-и):
@echo off
set /a res=%1+%2
echo res
pause
Метка — это именованное место в коде, она создается с помощью команды «:name»
А этот переходит на метку :m и продолжает выполнение, начиная с нее
rem куча кода
:m
rem куча кода
goto m
rem куча кода
И в завершение статьи, хочу сказать о команде call. Она превращает в последующей команде «%%» в «%», а переменные — на их значения. Пример использования:
call echo %%str:~%a%,%b%%%