Reputation: 976
I'm trying to write my own batch files to switch npm versions (just for fun).
@echo off
for /f "delims=" %%i in ('npm -v') do set output=%%i
move "%NPM_PATH%" "%NPM_PATH%-%output%"
FOR %%A IN (%*) DO (
IF "%%A"=="--change" (
SETLOCAL EnableDelayedExpansion
SET /A c=1
ECHO "ID : VERSION"
ECHO -------------------------
FOR /F "tokens=*" %%F in ('dir /on /b /a:d /p "%NPM_DIR%"') DO (
ECHO !c! : %%F
SET dir_!c!=%%F
SET /a c=c+1
)
set /p id="enter version ID: (e.g. !dir_1! enter 1):"
set target_dir= "dir_!id!"
echo !target_dir!
)
)
I can echo out the right variable I want to abstract.
But how do I actually output the value of !target_dir!
?
Example:
User selects 1
echo !target_dir!
will print dir_1
to the screen.
But when I use next echo !dir_1!
then npm-4.0.0
would be printed.
How do I now output npm-4.0.0
when the user inputs 1
?
Upvotes: 1
Views: 145
Reputation: 976
As per @Aacini I just needed to change this line: set target_dir= "dir_!id!"
to this one: : for %%i in (!id!) do set target_dir=!dir_%%i!
Upvotes: 0
Reputation: 49127
I suggest using the following code with the second suggestion offered by Aacini used in code and some other improvements:
@echo off
for /F "delims=" %%I in ('npm.bat -v') do set "output=%%I"
move "%NPM_PATH%" "%NPM_PATH%-%output%"
for %%A in (%*) do (
if "%%A" == "--change" (
setlocal EnableDelayedExpansion
cls
set "Count=1"
echo ID : VERSION
echo -------------------------
for /F "tokens=*" %%F in ('dir /A:D /B /ON "%NPM_DIR%"') do (
if !Count! LSS 10 (
echo !Count! : %%F
) else (
echo !Count! : %%F
)
set "dir_!Count!=%%F"
set /A Count+=1
)
echo.
set "id=1"
set /P "id=Enter version ID: (e.g. !dir_1! enter 1): "
for %%I in (!id!) do set "TargetDir=!dir_%%I!"
echo !TargetDir!
endlocal
)
)
Why for %%I in (!id!) do set "TargetDir=!dir_%%I!"
assigns the value of the environment variable with name dir_X
with X
being the entered number stored in environment variable id
is explained in detail in Aacini's answer on Arrays, linked lists and other data structures in cmd.exe (batch) script.
For the applied improvements see:
Why is no string output with 'echo %var%' after using 'set var = text' on command line? which is about spaces around equal sign in environment variable assignment and what is the difference between set variable="value"
and set "variable=value"
.
change directory command cd .. not working in batch file after npm install explaining what the command setlocal
without or with 1 or more parameters does and why in batch code above also endlocal
is explicitly specified in the --change
branch inside the outer FOR loop processing the arguments passed to the batch file.
It is advisable using environment variables with a self-explaining name in CamelCase
notation. This has the advantage of knowing what the variable is for and makes it easier to search for all occurrences of a variable. It is a bit difficult to search for a variable with name c
as a single character often occurs in many strings.
The command set
with option /A
means everything next should be interpreted as arithmetic expression. This means that the string after the equal sign is split up into a list of strings using spaces/tabs as string separators. Each string which could be interpreted as decimal, octal or hexadecimal number is converted to a 32-bit signed integer. All other strings which are not operators are interpreted as name of a variable whose value should be converted to a 32-bit signed integer. If the variable does not exist or has not a number as value, 0
is used for the variable. Then the arithmetic expression is evaluated and the result is converted back from integer to string. Finally the result string is assigned to the environment variable left to the equal sign. So with SET /A c=1
at lot of extra work is done in comparison to SET "c=1"
although the result is the same, a string with value 1
is assigned to variable with name c
. Therefore it is recommended not using /A
on assigning a value to an environment variable except there is a very good reason to do so like a primitive check for string being really a number. Note: An assignment like set /A c=009
results in an error message because of 009
being an invalid octal number and c
is not defined or keeps its current value in case of being already defined while set c=009
works.
When a batch user is prompted for a string, the user has the freedom to just hit RETURN or ENTER without entering anything at all. In this case the environment variable keeps its current value or is still not defined if it was not defined already before prompting the user. This explains why set "id=1"
is present in batch code above before prompting the user. Well, it is not checked if the user has really entered a number and if this number is within 1
... !Count!
, but perhaps this is not really necessary although a typing mistake could always occur.
Upvotes: 1