Windows Scripting: Difference between revisions
Line 3: | Line 3: | ||
chdir /D %~dp0 |
chdir /D %~dp0 |
||
The /D allows to change drives too. |
The /D allows to change drives too. |
||
=== remove quotes from an argument === |
|||
<pre> |
|||
@echo off |
|||
call :func1 "I am a long, long string." |
|||
exit /B 0 |
|||
:func1 |
|||
echo %1 |
|||
echo %~1 |
|||
exit /B 0 |
|||
</pre> |
|||
Output: |
|||
"I am a long, long string." |
|||
I am a long, long string. |
|||
=== save the current directory and return to it === |
=== save the current directory and return to it === |
Revision as of 14:16, 28 February 2024
directory of current script
change to the directory of the executed script:
chdir /D %~dp0
The /D allows to change drives too.
remove quotes from an argument
@echo off call :func1 "I am a long, long string." exit /B 0 :func1 echo %1 echo %~1 exit /B 0
Output:
"I am a long, long string." I am a long, long string.
save the current directory and return to it
set DIR_START=%cd% cd whereEver/AndDoStuff cd %DIR_START%
functions
@echo off echo 1 call :func_1 2 call :func_1 3 echo 4 exit /B :func_1 echo %1 (called in a function) exit /B 0
Output:
>test 1 2 (called in a function) 3 (called in a function) 4
parameters
- Parameters to a script are %1 to %9
- %0 is the call and should contain the script name
- %10 does not exist
- %* "is" all parameters, even if there are 15
- if you want to have more than 9 parameters, google for shift or use something like
FOR %%A IN (%*) DO ( echo xxx %%A xxx )
Output:
>test 1 2 3 4 5 6 7 8 9 10 11 12 13 x 1 x x 2 x x 3 x x 4 x x 5 x x 6 x x 7 x x 8 x x 9 x x 10 x x 11 x x 12 x x 13 x
test for parameters
@echo off if [%1]==[] ( echo Parameter 1 missing! ) else ( echo Paramater 1 found: %1 )
- '[' and ']' around "%1" are just for the case it is empty. You can use anything you want:
if xx%1xx==xxxx (
- you need a space between "[]" and '(' in the if condition
- the "(" must be on the same line as the if
- the ") else (" can not be on multiple lines
text color
The documentation from MS is here: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences?redirectedfrom=MSDN
You will need to output a certain character which is just called ESC. It is the "character" with the number 27 in the ASCII table, so you can create it on the console if you hold ALT and enter with the numlock digits "027". When you release ALT afterwards you should get "^[". You can try it but it will be of not much use. It would be:
- ALT + 027
- [92m
- <return>
Now your prompt should be green. To get back to normal:
- ALT + 027
- [0m
- <return>
Try the following script: (create a test.cmd and execute it from the command line)
@echo off for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a" set GREEN=%ESC%[92m set DEFAULT=%ESC%[0m set ERROR=%ESC%[101;93m call :out Dies ist ein erster Test. call :out Dies ist ein zweiter Test. call :outError This is not a test, please leave this script immediately! set ESC= set ERROR= SET GREEN= exit /B :out echo %GREEN% %* %DEFAULT% exit /B :outError echo %ERROR% %* %DEFAULT% exit /B
You can create the ESC variable with
set ESC=
then use ALT+0+2+7 to get the correct "character" at that spot. It will look like:
set ESC=ESC
but the second ESC will look different, because it "is" just one character. Copy/paste will be a burden and just looking at such a script will not tell you how to recreate it. That is the reason the variant where you create the ESC with the for (I got the idea from someone called Aacini in a forum) is much much better in my opinion.
echo with color by calling a script
As always, the paths will have to be changed depending on your setup. I am using
bin win helpers create-links 32 64
In "helpers" I have "create-argCount.cmd" (see above or below on this wiki page) and "echo-color.cmd".
Create a file "echo-color.cmd":
@echo off for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a" set GREEN=%ESC%[92m set DEFAULT=%ESC%[0m set RED=%ESC%[101;93m call %~dp0\create-argCount.cmd %* if [%argCount%]==[2] ( if /I [%~1]==[DEFAULT] ( call :default %~2 exit /B ) else if /I [%~1]==[GREEN] ( call :green %~2 exit /B ) else if /I [%~1]==[RED] ( call :red %~2 exit /B ) ) call :syntax set ESC= set RED= SET GREEN= exit /B :syntax echo echo-color v1 by Andreas Duffner, 2024 echo Syntax: echo-color ^</?^> echo echo-color ^<COLOR^> ^<"TEXT"^> echo Example: echo-color RED "You are doing it wrong!" exit /B :default echo %DEFAULT%%*%DEFAULT% exit /B :green echo %GREEN%%*%DEFAULT% exit /B :red echo %RED%%*%DEFAULT% exit /B
In "create-links" I have multiple files for link creation, for example "create-links-for-ssh.cmd":
@echo off set DIR_START=%cd% set HELPERS=%~dp0\..\helpers chdir /D %~dp0 cd ..\..\..\documents\always\keys\andreas\ set DIR_FILES=%cd% cd /D c:\Users\Andreas\.ssh\ set FILE=config mklink /H %FILE% %DIR_FILES%\%FILE% if %ERRORLEVEL%==0 (call %HELPERS%\echo-color green "%FILE%: Ok") else (call %HELPERS%\echo-color red "%FILE%: Error") set FILE=authorized_keys mklink /H %FILE% %DIR_FILES%\%FILE% if %ERRORLEVEL%==0 (call %HELPERS%\echo-color green "%FILE%: Ok") else (call %HELPERS%\echo-color red "%FILE%: Error") set FILE=id_rsa mklink /H %FILE% %DIR_FILES%\%FILE% if %ERRORLEVEL%==0 (call %HELPERS%\echo-color green "%FILE%: Ok") else (call %HELPERS%\echo-color red "%FILE%: Error") set FILE=id_rsa.pub mklink /H %FILE% %DIR_FILES%\%FILE% if %ERRORLEVEL%==0 (call %HELPERS%\echo-color green "%FILE%: Ok") else (call %HELPERS%\echo-color red "%FILE%: Error") set FILE=id_rsa.ppk mklink /H %FILE% %DIR_FILES%\%FILE% if %ERRORLEVEL%==0 (call %HELPERS%\echo-color green "%FILE%: Ok") else (call %HELPERS%\echo-color red "%FILE%: Error") set FILE=known_hosts mklink /H %FILE% %DIR_FILES%\%FILE% if %ERRORLEVEL%==0 (call %HELPERS%\echo-color green "%FILE%: Ok") else (call %HELPERS%\echo-color red "%FILE%: Error") cd %DIR_START% pause
output empty line
Put a period immediately after the echo. No space between echo and period.
@echo off echo Normal 1 echo. echo Normal 2
calling another script and keeping the variables it creates
call %~dp0\SetDateTimeToVariables-Europe.cmd
In this call we call a script in the same directory as the calling script. Keep in mind that the working directory does not have to be the directory of the working script, so we have to be more exact when we call the 2nd script.
Creating files with current date/time in the name
Get the current date/time in European format into a variable
Create the file "SetDateTimeToVariables-Europe.cmd":
@echo off rem v2 (2022-11-23), use this for dates like "2022-11-23" for /f "tokens=1-3 delims=- " %%a in ('date /T') do set year=%%a for /f "tokens=1-3 delims=- " %%a in ('date /T') do set month=%%b for /f "tokens=1-3 delims=- " %%a in ('date /T') do set day=%%c set TODAY=%year%-%month%-%day% rem @echo today: %TODAY% year: %year% month: %month% day: %day% for /f "tokens=1 delims=: " %%h in ('time /T') do set hour=%%h for /f "tokens=2 delims=: " %%m in ('time /T') do set minutes=%%m set NOW=%hour%-%minutes% rem @echo %NOW%
Use the earlier created script in one of your normal scripts
In this example we create a backup of a Tekkit-Lite installation:
set DIR_SAVES_PARENT=d:\Games\MineCraft\Technic\installed\modpacks\tekkitlite\ set DIR_SAVES="saves" set DIR_ARCHIVE=d:\data\_temp-backup\ set PATH_7_ZIP=%~dp0\32\7za set BACKUP_NAME="MC-Tekkit-Lite-All-Worlds" set DIR_START=%cd% call %~dp0\SetDateTimeToVariables-Europe.cmd cd /D %DIR_SAVES_PARENT% rem echo %TODAY% %PATH_7_ZIP% a -tzip %DIR_ARCHIVE%\%TODAY%--%NOW%-%BACKUP_NAME%.zip -r %DIR_SAVES% cd /D %DIR_START%
The above script is complete and working. Of course you have to have 7zip in the correct directory and bla, bla bla. You get it. Right?
The relevant parts are:
call %~dp0\SetDateTimeToVariables-Europe.cmd
and
%PATH_7_ZIP% a -tzip %DIR_ARCHIVE%\%TODAY%--%NOW%-%BACKUP_NAME%.zip -r %DIR_SAVES%
The call to SetDateTimeToVariables-Europe.cmd creates variables and fills them with content and later we use these variables to create a meaningful filename.
escape character
If you want to output certain symbols, Windows will not allow it because they have a meaning are interpreted. The Escape character for the normal Windows command shell is '^'.
@echo off echo abc def ^<xxx^>
count of arguments
create a helper script "create-argCount.cmd":
set argCount=0 for %%x in (%*) do Set /A argCount+=1
create a script "test.cmd" that uses it:
@echo off call create-argCount.cmd %* echo Count of arguments: %argCount%
call it:
test 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Count of arguments: 15
structure for a script to check for parameters
Do only check for the correct version, anything else is wrong. No need to check for "/?" or "--help".
Keep in mind that this is a simplified example. You will need to watch for correct working directories and paths. The call to create-argCount.cmd could need a "%~dp0" of some kind in front or something completely different, depending on your setup.
This is an example for a script called "test.cmd":
@echo off call create-argCount.cmd %* if %argCount% == 2 ( echo todo ) else ( call :syntax ) exit /B :syntax echo test v1 by Andreas Duffner, 2024 echo Syntax: echo test ^<color^> ^<"text"^> echo test RED "You are doing it wrong!" exit /B