I have a Script that reads other .bat Files and counts the Commentlines. I pass the .bat file that i want to test as a parameter.
For example, this is how i start my script.
C:\User\User\Desktop>CommentReader.bat test.bat
Right now test.bat needs to be in the same folder with the Skript.
I want the option that I can pass multiple .bat files that need testing and the option that I can pass the path too. for example:
C:\User\User\Desktop>CommentReader.bat D:\testfolder\test1.bat E:\test2.bat test3.bat
I also want to pass commands for example /l so the script also reads empty lines.
C:\User\User\Desktop>CommentReader.bat /l D:\testfolder\test1.bat E:\test2.bat test3.bat
I know how I can code that it should also read empty lines but
what is the best way to go through my parameters and check the information?
My Idea was something like this:
FOR /f tokens=1,2,3,4,5,6,7,8,9, delims= " %%a in (%*) DO (
)
But maybe there is a better way?
As Stephan stated in the comments section, SHIFT is what you're looking for. This script will loop through all parameters and echo them out. Just replace the ECHO command with your actual code.
#ECHO OFF
:LOOP
IF NOT "%1"=="" (
ECHO %1
SHIFT
GOTO LOOP
)
Your first parameter is always %1, the second one is %2 and so on. The SHIFT command will "forget" the original %1 and decrease all indices by 1, so %2 will become %1, %3 will become %2 and so on. As soon as you reach the last argument SHIFT will turn %1 into an empty string so that you beak out of the loop.
Related
I have a small problem with a .bat file that I have to build to manipulate a specific .csv.
I want the .bat to read the line of the file, and then check for the first three letters of that line. At the end there should be n-files where file xxx.csv contains the lines of the input.csv with xxx as the first three letters of line.
First things first, I don't even know if it is possible to do it this job in a batch-file, because the file has >85000 lines and may even get much bigger. So if it is impossible you can directly tell me that.
for /f "delims=" %%a in (input.CSV) DO (
echo %%~a:~0,3
pause
)
I want to "output" the first three letters of %%a.
It would be great if you could help me.
Phil
Substring substitution only works with environment variables (%var%), but not with metavariables (%%a) (as Mofi already commented). And because you are setting and using a variable within the same command block, you need delayed expansion:
setlocal enabledelayedexpansion
for /f "delims=" %%a in (input.CSV) DO (
set "var=%%~a"
echo !var:~0,3!
pause
)
(there are methods without delayed expansion, but they make use of call, which slows things down)
I am trying to pass an array to a conca.bat file so I can concatenate all the strings that list or array has.
I have been able to concatenate, buty just if I put the Array by hand, but I am not able to do it when I pass ii from command line...
It works:
FOR %%i IN (12346,49874,48954) DO call :concat %%i
set var=%var%%1;
Doesn´t work
FOR %%i IN %1 DO call :concat %%i
set var=%var%%1;
What is the structure I must follow from the command prompt?
conca.bat "12346,49874"
or
conca.bat {12346,49874}
There are no real lists or arrays in CMD. However, if I've understood your question correctly, you are trying to do something like this:
concat.bat 123 456 789
and want the output to be 123456789. If this is the case, SHIFT is the magic command you are looking for. This should do it:
#ECHO OFF
SET concatString=
:LOOP
IF [%1]==[] GOTO ENDLOOP
SET concatString=%concatString%%1
SHIFT
GOTO LOOP
:ENDLOOP
ECHO %concatString%
PAUSE
When you pass parameters to a bat file via command line, they are accessible via %1, %2, %3 and so in. This means for concat.bat a b c that %1 is a, %2 is b and %3 is c. The only problem is that we might not know how many parameters there will be and you want your script to work with only one parameter as well as with 100 of them. At this point SHIFT is saving the day.
SHIFT does one simple thing. It moves the index of the parameters to the right, so the "old" %1 disappears, %2 becomes %1, %3 becomes %2 and so on. We just keep on looping until the last passed parameter becomes %1. After another shift there is no value left which can be assigned to %1 so [%1]==[] becomes true and we jump out of the loop.
I have a batch file test.bat
I understand we can give it multiple arguments and take those values using %1, %2, and so on. But I do not know how many arguments will be given. I thought of constructing an array and for loop to decide. But the point I am failing is constructing the for loop.
what I did is:
set count=0
// for loop until we have arguments left
set list[%count%]=%var%
set /A count=count+1
I know little bit of for loop in batch files, but I do not quite understand how to use in this scenario. Number of arguments are unknown. Any direction would be appreciated?
%* contains all arguments.
you could
for %%a in (%*) do echo %%a
or use shift, which advances %1 to the next argument and so on.
:loop
echo %1
shift
if "%1" neq "" goto :loop
I'm creating a batch file that will call a few other batch files. One of the batch files to be called has a "CLS" in it. Is there some way I can get the wrapping batch file to ignore the child "CLS" call while still letting the CLS work when the child batch file is called directly from the command line?
Here is a real ugly hack :-)
The CLS screen command does not work if stdout is redirected to con: - it prints the Form Feed character (0x0C) to the screen. On my machine it looks like the female symbol.
#echo off
:: Normal call, CLS in called batch clears the screen
call batch2
:: Redirected call, CLS in called batch prints <FF> character to screen (without newline)
call batch2 >con:
Advantage - No need to modify your child script.
Disadvantage - The unwanted <FF> character appears in the output.
Hmm - quite how long IS a piece of string?
Generally, you could try this in your CALLed batch:
#echo off
setlocal
set skipcls=%1
if defined skipcls (if "%skipcls%"=="::" (shift) else (set "skipcls="))
...
%SKIPCLS% cls
...
Then call your batch with an extra first parameter ::
If the first parameter is :: it will be shifted out and skipcls will be set to ::; otherwise skipcls will be empty, hence the %skipcls% CLS line will be skipped or executed...
Amendment:
Perhaps
#echo off
setlocal
if "%~1"=="::" (shift&set "skipcls=REM ") else (set "skipcls=")
...
%SKIPCLS% cls
...
would be simpler. Setting skipclsto a value of REMSPACE rather than :: would allow the technique to be used more reliably within parenthesised constructs.
Of course, another approach would be to set skipcls appropriately in the caller routine.
OR set skipcls to any non-empty value you like and use
if [not] defined skipcls ...
which supports constructs like if it's set do this, if not do that.
And of course, it's not restricted to CLS, so perhaps a different variable name should be used.
And if you're really feeling adventurous, you could set redirect to >>"a_filename" in the caller and then have
%redirect% ECHO whatever
to steer output to an externally-controled destination.
Seems to be many ways to apply a simple concept.
You could create a temp batch file, where all cls commands have been ingnored:
setlocal enabledelayedexpansion
set target=targetname.bat
for /f "usebackq delims=" %%a in ("%target%") do (
set line=%%a
Echo !line:cls=Rem Cls! >> temp_%target%
Echo !line:CLS=Rem Cls! >> temp_%target%
Echo !line:Cls=Rem Cls! >> temp_%target%
Rem Include CLs ClS cLS, etc. if the person who wrote the file is not case consistent
Rem : (
set line=
)
call temp_%target%
set target=
Endlocal
And that should do what you want perfectly.
Mona
I have 2 batch files.
The first one needs an input argument which is a path of a parent folder. It reads the names of all subfolders inside the parent folder and executes the second batch file for each subfolder.
BATCH FILE 1
#echo off
for /d %%Y in (%1/*) do (
set SubfolderNameAndPath=%%Y
call batch2.bat %SubfolderNameAndPath%
)
The second batch file uses as input argument the SubfolderNameAndPath and executes an Evaluate.exe for all the files that exist in each subfolder. It saves the results of the Evaluate.exe to a text file "results" with an extension that carries the name of the subfolder that each time has been accessed. (results_%~n1.txt).
BATCH FILE 2
#echo off
for %%X in (%1/*) do (
echo Evaluate.exe %%X AnotherArgumentHere -o results_%~n1.txt
)
When I run the batch1 (batch1.bat ParentFolderPath) even if it seems to call the batch2.bat, the batch2.bat is not executed. I believe that something goes wrong with the way that I define the input arguments for the batch2.bat but I cannot figure out what it is.
The %SubfolderNameAndPath% does not contain any spaces. Neither the path to the folder does.
I would really appreciate your help on that.
Well, first, when inside a bracketed pair you can't set a variable then access it with the %'s. You must first (before the for loop) setlocal enabledelayedexpansion, then access your variables with the !'s rather than the %'s.
But since you do not do anything with %SubfolderNameAndPath% anyway, you should just eliminate it.
Second, you need to compensate for paths containing spaces, so hopefully my code below will work out for you. To do this, batch uses a special notation for arguments passed to to remove double quotes around them. So, if %1 = "This string", then %~1 = This string. Also, if %1 = This string, then %~1 still = This string. So there is no drawback to using the %~1 notation, unless you want to retain any double quotes.
So, int batch1.bat, we remove any potential quotes surrounding %1, and then place double-quotes around %~1/*, and also double-quote %%Y just in case there are spaces in it.
batch1.bat
#echo off
for /d %%Y in ("%~1/*") do call batch2.bat "%%~Y"
Then we do the same thing for batch2.bat, but more of it.
batch2.bat
#echo off
for %%X in ("%~1/*") do (
echo Evaluate.exe "%%~X" AnotherArgumentHere -o "results_%~n1.txt"
)
EDIT: 2012/09/05 15:21
How's this grab you? Instead of calling a seprate batch:
for /d %%x in (%1\*) do (
for /f "tokens=*" %%y in ( 'dir /b /a:-d "%%~dpnxx"' ) do (
echo Evaluate.exe %%~nxy AnotherArgumentHere -o "results_%%~nxx.txt"
)
)
(The above can be put all on one line, just remove the brackets.)
I'm assuming the output is:
Evaluate.exe <file_name> AnotherArgumentHere -o "results_<directory_name>.txt"