CMD program "for" loop error - cmd

echo off
set apk[0]=apk
for /r %%a in (.apk) do call array.bat add apk %%a
call array.bat len apk length
echo apk files found = %length%
for /l %%G in (1,1,%length%) do (
call array.bat getitem apk %%G item
echo %item%
)
echo Pick one:
set /p pick=
call array.bat getitem apk %pick% chose
echo.
echo You picked %chose%.
pause
In the above code i get length of apk array as 9 but the for loop prints ECHO is off 10 times?!
I am able to access to individual elements of the array o_O and also down the code after the user picks the choice it displays correctly. What am i doing wrong?

As a very quick fix, try
call echo %%item%%
This is generation 7,863 of delayedexpansion. There are hundreds of SO entries on this subject. Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.
Note therefore the use of CALL ECHO %%var%% which displays the changed value of var. CALL ECHO %%errorlevel%% displays, but sadly then RESETS errorlevel.
Note also that your item-displayed using your original code is the last item set in a prior run. You do not have a setlocal command in your batch, so the environment changes are established permanently, not backed out at the end of each batch. The consequence is that you are running with a contaminated environment.

Related

Windows Cmd Loop name and create folders

I'm trying to figure out how to create a certain number of folders in a Windows batch file. I want to ask the user how many folder they want, and then use that collected number to loop the asking for names of those folders and make them. Here is what I have so far:
pushd C:\Users\%username%\Desktop
set /p FolderLoop="How many folders?: "
for /l %%x in (1, 1, %FolderLoop%) do (
set /p folder="Folder: " %%x
md %folder% %%x
)
The problem I keep having is that I can not make the folders with the proper collected names. The closest I have gotten so far is creating the right amount of folders, but with sequential numeric names (1,2,3, etc.) based om the FolderLoop variable.
You need to read any of the hundreds of responses on SO with regard to delayedexpansion.
Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).
Within a block statement (a parenthesised series of statements), REM statements rather than the broken-label remark form (:: comment) should be used because labels terminate blocks, confusing cmd.
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.
Note therefore the use of CALL ECHO %%var%% which displays the changed value of var. CALL ECHO %%errorlevel%% displays, but sadly then RESETS errorlevel.
You need delayed expansion:
setlocal enabledelayedexpansion
pushd C:\Users\%username%\Desktop
set /p FolderLoop="How many folders?: "
for /l %%x in (1, 1, %FolderLoop%) do (
set /p "folder=Folder: "
md "!folder!"
)
(the %%x after set /p does nothing. I removed it. I also removed it from md, you don't need it - except you want the counter be part of the foldername.)

ren won't use my variable from one lina above

I've got a strange problem. I want to rename multiple files in a folder.
So far, so easy - in theory. I use this script:
cd C:\Test
for %%i in (*(7*) do (
set name="%%i"
ren "%name%" "%name:~0,-15%.txt"
)
pause
The strange thing is that he seems to not use the variable "name" I declared
one line above the ren command as you can see in what the console prints:
C:\Test>(
set name="ttttt(7xAAdoc) .txt"
ren "" "~0,-15.txt"
)
What am I missing here? I am running Windows 7, if thats important.
Thanks for any help.
Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.
In your case,
cd C:\Test
setlocal enabledelayedexpansion
for %%i in (*(7*) do (
set "name=%%i"
ren "%name%" "!name:~0,-15!.txt"
)
note the positioning of the quotes in the first set. The set "var=value" syntax ensures that any trailing spaces on the batch line are not included in the value assigned to var. As you had it, name would be assigned a "quoted" value and the ren command (had it worked) would have been `ren ""filename"" ""firstpartoffilename".txt"

How to combine number and string in batch file

I am using batch file to display some kind of number such as
00_test.txt 01_test.txt...10_test.txt 11_test.txt
Hence, This is my code. But I cannot show as my expectation
FOR /L %%x IN (1,1,10) DO (
set "extension=.txt"
set "fullname=%x%_test%extension%"
echo.%fullname%
)
The result of above code are _test.txt _test_txt but expected result are
00_test.txt 01_test.txt
Could you help me edit it?
#echo off
setlocal enabledelayedexpansion
set "baseName=_test"
set "extension=.txt"
for /l %%a in (1 1 10) do (
set "n=0%%a"
echo !n:~-2!%baseName%%extension%
)
When a block of code (in your case the for and the code inside parenthesis) is reached by the parser, all variable reads are replaced with the value in the variable before starting to execute the code. So, if a variable is changed inside the block and the value needs to be retrieved inside the same block, it is necessary to use delayed expansion, telling the parser that variables that are referenced as !var! (instead of %var%), should not be replaced at parse time, its value should be accessed at execution time.
So, in this code %baseName% and %extension% are used with usual syntax as its value does not change inside the for code block, but !n! uses delayed expansion. Its value changes inside the block and this value must be accessed inside the same block.
The concatenation of a 0 prefix and the extraction of two characters on the right from the variable ensure the presence of the initial 0 for values 1 to 9
Try %%x instead of %x:
FOR /L %%x IN (1,1,10) DO (
set "extension=.txt"
set "fullname=%%x%_test%extension%"
echo.%fullname%
)

using for loop to input multiple data

I am new to programming. Here is my dilemma. I have to replace multiple files in multiple locations across multiple computers.
I have written a bat script where I am defining all the variables and calling a txt file with appropriate information. For example -testing.txt has the values
Apple, Potato,Beef
Apple, Potato,Pork
The logic I am applying is as follows: I am using this txt file for reading and then going to each location to change the file
set Path=%Path%;c:\Tools\UnxUtils\usr\local\wbin
SET SORC=C:\tools\logosource\NEWImages\ApiSite\Content
for /F "usebackq delims=, tokens=1-3" %%a in (C:\tools\xxxx\testing.txt) do (
SET HOSTNAME=%%a
SET CUSTNAME=%%c
SET STYPE=%%b
SET DEST=\\%HOSTNAME%\c$\Documents and Settings\blahblah\My Documents\%CUSTNAME%\%STYPE%\goodman\
echo HOSTNAME is %HOSTNAME%
echo CUSTNAME is %CUSTNAME%
echo STYPE is %STYPE%
echo DEST is %DEST%
echo SORC is %SORC%
)
copy "%DEST%\ApiSite\Content\images\michael.gif" "%DEST%"
copy /b /y "%SORC%\images\george.gif" "%DEST%\ApiSite\Content\images\michael.gif"
goto End
:Error
ECHO Error! You must pass in a servername
goto End
:End
The problem is that my loop is only reading the last line my txt file. ie. it reads "Apple, Potato,Pork" and sets the DEST TO THAT VALUE.
What i really want is to read line 1 (Apple, Potato,Beef) set the DEST using these parameters and change the files, then go back and read the second line (Apple, Potato,Pork) and set the DEST using these parameters and change the files.
Actually your code is reading every line in the file, but your logic is wrong.
Your main problem is you want to do the COPY statements for each line, but you have the COPY statements outside the loop. Of course they will only get executed once, and the values used will be the values that were set by the last line in the file. The solution is to move the COPY statements inside the loop.
Your other problem is you are attempting to set a variable within a parenthesized block, and then access the value using %var% - that cannot work because the expansion occurs when the statement is parsed and the entire block is parsed once before any lines are read. You could solve that problem by using delayed expansion, (type HELP SET from the command line prompt for more information about delayed expansion). But there really isn't any need to save the values in variables. Simply use the FOR variables directly. Because the DEST is used multiple times, I used an additional FOR loop to define a %%d variable that contains the DEST value. The ~ removes the quotes that the FOR loop added.
Also, you are ending the script by using GOTO END and defining an :END label at the end of file. That works, but there is an implicit :EOF label at the end of every script. You can simply use GOTO :EOF without defining a label. The other option is to use EXIT /B
You have an :ERROR routine that is not being called - I presume you have additional code that you are not showing.
set Path=%Path%;c:\Tools\UnxUtils\usr\local\wbin
SET "SORC=C:\tools\logosource\NEWImages\ApiSite\Content"
for /F "usebackq delims=, tokens=1-3" %%a in (C:\tools\xxxx\testing.txt) do (
for %%d in (
"\\%%a\c$\Documents and Settings\blahblah\My Documents\%%b\%%b\goodman\"
) do (
echo HOSTNAME=%%a
echo CUSTNAME=%%c
echo STYPE=%%b
echo DEST=%%~d
echo SORC is %SORC%
copy "%%~d\ApiSite\Content\images\michael.gif" "%%~d"
copy /b /y "%SORC%\images\george.gif" "%%~d\ApiSite\Content\images\michael.gif"
)
)
exit /b
:Error
ECHO Error! You must pass in a servername
exit /b

Random variable not changing in "for" loop in windows batch file

I'm trying to print out a Random number multiple times but in the for loop I use, it doesn't reset the variable. Here's my code.
#echo off
for %%i in (*.txt) do (
set checker=%Random%
echo %checker%
echo %%i% >> backupF
)
echo Complete
There are 5 text files and so I want it to print 5 different random numbers but it just prints the same random number 5 times. Any help would be greatly appreciated. Thanks!
I'm not sure how you've been able to have it print even one random number. In your case, %checker% should evaluate to an empty string, unless you run your script more than once from the same cmd session.
Basically, the reason your script doesn't work as intended is because the variables in the loop body are parsed and evaluated before the loop executes. When the body executes, the vars have already been evaluated and the same values are used in all iterations.
What you need, therefore, is a delayed evaluation, otherwise called delayed expansion. You need first to enable it, then use a special syntax for it.
Here's your script modified so as to use the delayed expansion:
#echo off
setlocal EnableDelayedExpansion
for %%i in (*.txt) do (
set checker=!Random!
echo !checker!
echo %%i% >> backupF
)
endlocal
echo Complete
As you can see, setlocal EnableDelayedExpansion enables special processing for the delayed expansion syntax, which is !s around the variable names instead of %s.
You can still use immediate expansion (using %) where it can work correctly (basically, outside the bracketed command blocks).
Try by calling a method.
#echo off
pause
for %%i in (*.txt) do (
call :makeRandom %%i
)
echo Complete
pause
:makeRandom
set /a y = %random%
echo %y%
echo %~1 >> backupF
on my system I have to write
set checker=Random
instead of
set checker=!Random!

Resources