I currently have a batch file that is going through a text file and assigning each line into an array. I want to iterate through the loop and remove a certain number of characters from every value in the array. Is this possible to do?
#ECHO off
findstr /C:"number" /C:"type" testFile.txt > oneresult.txt
set "file=oneresult.txt"
set /A i=0
timeout /t 1
echo ---------------Results--------------- > results.txt
for /f "tokens=*" %%x in (oneresult.txt) do (
call echo %%x >> results.txt
call set array[%i%]=%%x
set /A i+=1
)
call echo %i% files received >> results.txt
del "oneresult.txt"
So right now it just prints the retrieved strings from testFile.txt and then they are eventually placed into result.txt. I would like all the strings that come from the testFile.txt to have the first 10 characters removed. If there is an easier way please let me know. So far this is what I have found but I am also a bit of a batch noob.
Just figured it out without the array and posting the answer for anyone else that may be searching in the future:
#ECHO off
findstr /C:"number" /C:"type" testFile.txt > oneresult.txt
set /A i=0
timeout /t 1
echo ---------------Results--------------- > results.txt
for /f "tokens=*" %%x in (oneresult.txt) do (
setlocal enabledelayedexpansion
call set print=%%x
call set newprint=!print:~32!
call echo !newprint! >>results.txt
endlocal
set /A i+=1
)
call echo %i% files received >> results.txt
del "oneresult.txt"
You use several call's in your code without having understood that these pseudo calls are usually used for a different type of delayed expansion not requiring setlocal enabledelayedexpansion, but to double the percent signs.
the intermediate file oneresult isn't necessary, one for /f to parse the output of the findstr is sufficient.
One set of parentheses enclosing all output lines can redirect to results.txt
#ECHO off
set /A i=0
(
echo ---------------Results---------------
for /f "tokens=*" %%x in (
'findstr /C:"number" /C:"type" testFile.txt'
) do (
set print=%%x
call echo:%%print:~32%%
set /A i+=1
)
call echo %%i%% files received
) > results.txt
The following code with setlocal enabledelayedexpansion is functional identical
#ECHO off&Setlocal EnabledelayedExpansion
set /A i=0
(
echo ---------------Results---------------
for /f "tokens=*" %%x in (
'findstr /C:"number" /C:"type" testFile.txt'
) do (
set print=%%x
echo:!print:~32!
set /A i+=1
)
echo !i! files received
) > results.txt
Related
Ok. this is a self updating batch file. I just simplified the problem from a bigger file.
this is a windows batch file(.bat) that upon execution should open itself and update first line
SET variableName=D:\Data
setlocal enableextensions enabledelayedexpansion
set /A i=0
for /f "tokens=*" %%f in ('type "%0"^&cd.^>"%0"') do (
set /A i=!i!+1
if !i! EQU 1 (
echo SET variableName=D:\Data2>>%0
) else (
echo %%f>>%0
)
)
endlocal
so let explain the situation.
i have !i! variable in lines 5 and 6. after executing this file, the variable in each line will replace by line number. it obviously because of echo %%f>>%0 that could not ignore and escape variable.
and my question is how to solve this problem?
another less problem is that the above code ignores spaces at beginning of line (indents) and generates a flat file.
the result of executing this file is:
SET variableName=D:\Data2
setlocal enableextensions enabledelayedexpansion
set /A i=0
for /f "tokens=*" %%f in ('type "%0"^&cd.^>"%0"') do (
set /A i=5+1
if 6 EQU 1 (
echo SET variableName=D:\Data2>>%0
) else (
echo %%f>>%0
)
)
endlocal
Stopping expansion of the variable when executing the file is as simple as turning delayed expansion off prior to the line that updates the file, and pairing it with an endlocal.
Retaining the space / tab formatting is achieved by including delims= in the For loop options.
Set variableName=D:\Data
Setlocal enableextensions enabledelayedexpansion
Set /A i=0
For /f "tokens=* delims=" %%f in ('type "%0"^&cd.^>"%0"') do (
Set /A i+=1
If !i! EQU 1 (
Echo SET variableName=D:\Data2>>%0
) Else (
Setlocal DisableDelayedExpansion
Echo(%%f>>%0
Endlocal
)
)
Endlocal
set "variableName=D:\Data"
setlocal enableextensions enabledelayedexpansion
rem !test! exclaimations, %test% percentages
for /f "skip=1 delims=" %%A in ('
type "%~f0" ^&
^> "%~f0" echo set "variableName=D:\Data2"
') do (
setlocal disabledelayedexpansion
>> "%~f0" echo %%A
endlocal
)
endlocal
You can avoid counting as skip=1 can be used to skip the first line. Use delims= to avoid delimiting the line. tokens=* ignores delimiters at start of the line and get the remainder of the line so that can be omitted for this task.
The new first line is now in the for loop command instead of erasing the file to empty. If you echo more lines, then increase the skip number.
Also may need to use setlocal disabledelayedexpansion so exclamation marks are retained.
Modifying the same file that is being read can a risk, though I assume you understand the risk.
How can we split string using windows bat script?
for below .bat code snippet
#echo off & setlocal EnableDelayedExpansion
set j=0
for /f "delims=""" %%i in (config.ini) do (
set /a j+=1
set con!j!=%%i
call set a=%%con!j!%%
echo !a!
(echo !a!|findstr "^#">nul 2>nul && (
rem mkdir !a!
) || (
echo +)
rem for /f "tokens=2" %%k in(config.ini) do echo %%k
)
)
pause
below config file
Q
What's wrong when I del rem at the begin of rem for /f "tokens=2" %%k in(config.ini) do echo %%k
How can I get the /path/to/case and value as a pair?
for /f xxxx in (testconfig.ini) do (set a=/path/to/case1 set b=vaule1)
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q43407067.txt"
set j=0
for /f "delims=""" %%i in (%filename1%) do (
set /a j+=1
set con!j!=%%i
call set a=%%con!j!%%
echo !a! SHOULD BE EQUAL TO %%i
(echo !a!|findstr "^#">nul 2>nul && (
echo mkdir !a!
) || (
echo +)
for /f "tokens=2" %%k IN ("%%i") do echo "%%k"
for /f "tokens=1,2" %%j IN ("%%i") do echo "%%j" and "%%k"
)
)
ECHO ----------------------------
SET con
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q43407067.txt containing your data for my testing.
(These are setting that suit my system)
SO - to address your problems:
because the ) on that line closes the ( on the previous. The ) on that line closes the ( on the one prior. (I changed the rem to an echo so that the code would produce something visible) The first ( on the (echo !a! line is closed by the ) on the line following the (now) two for /f commands. and the ( on the for..%%i..do( is closed by the final ) before the echo -----
You can't delete that ) because it's participating in a parenthesis-pair.
You need a space between the in and the (.
I've shown a way. See for /?|more from the prompt for documentation (or many articles here on SO)
In your code, !a! is the same as %%i - so I've no idea why you are conducting all the gymnastics - doubtless to present a minimal example showing the problem.
Note that since the default delimiters include Space then if any line contains a space in the /path/to/case or value then you'll have to re-engineer the approach.
I' not sure if I understand what exactly it is you need, so what follows may not suit your needs:
#Echo Off
SetLocal EnableDelayedExpansion
Set "n=0"
For /F "Delims=" %%A In (testConfig.ini) Do (Set "_=%%A"
If "!_:~,1!"=="#" (Set/A "n+=1", "i=0"
Echo=MD %%A
Set "con[!n!]!i!=%%A") Else (For /F "Tokens=1-2" %%B In ('Echo=%%A'
) Do (Set/A "i+=1"
Set "con[!n!]!i!=%%B"&&Set/A "i+=1"&&Set "con[!n!]!i!=%%C")))
Set con[
Timeout -1
GoTo :EOF
remove Echo= on line 6 if you are happy with the output and really want to create those directories
I have a text file like this
myFile.txt:
apple
banana
grapes
I want to drag text file to batch file and set variables into an array like this:
array[0]=apple
array[1]=banana
array[2]=grapes
But i couldn't do that. My problem is not just printing them but i can't even do that. I'll do parse operations at the rest of batch file.
My Code:
#echo off
setlocal EnableDelayedExpansion
set i=0
for /f %%a in %1 do (
set /a i+=1
set array[!i!]=!a!
)
echo %array[0]%
echo %array[1]%
echo %array[2]%
endlocal
#echo off
setlocal EnableDelayedExpansion
set i=0
for /f "usebackq" %%a in ("%~1") do (
set /a i+=1
set array[!i!]=%%a
)
echo %array[1]%
echo %array[2]%
echo %array[3]%
rem Or:
for /L %%i in (1,1,%i%) do echo !array[%%i]!
endlocal
pause
I suggest you to read this answer.
I'm making a batch script to stop several services , however i get the syntax is incorrect error at second FOR which loops in serviceList.TEMP
setlocal EnableDelayedExpansion
setlocal enableExtensions
::queryex output file
sc queryex>services.TEMP
find /i /N "DISPLAY_NAME: Hotspot" services.TEMP>tmp1.TEMP
FOR /F "skip=2" %%G in (tmp1.TEMP) do (
set num=%%G
set num=!num:~1,3!
echo !num!>serviceList.TEMP
)
FOR %%X in (serviceList.TEMP) do (
set /a "SKIP_LINES=%%G+7"
set secondForFilter="skip=%SKIP_LINES%"
FOR /F %secondForFilter% %%Z in (services.TEMP) do (
call debug.cmd REM debug.cmd -> echo debug pause>nul
set serv=%%Z
set "serv=!serv: =!" REM Extract PID
set "serv=!serv::=!" REM Extract PID
set procID=!serv!
taskkill /pid %procID% /f >>debug.txt 2>>debug.txt
goto secondLoopEnd
)
:secondLoopEnd
)
del /S *.TEMP >>debug.txt 2>>debug.txt
the problem is here:
FOR %%X in (serviceList.TEMP) do (
set /a "SKIP_LINES=%%G+7"
set secondForFilter="skip=%SKIP_LINES%"
FOR /F %secondForFilter% %%Z in (services.TEMP) do (
call debug.cmd REM debug.cmd -> echo debug pause>nul
the usual approach when you set value in brackets context is to use delayed expansion but it wont work for parametrized for options.
Here you'll need a subroutine.
And you have GOTO in the for loop. GOTO breaks for context and the loops will be not called after goto is executed.
And rem cannot be used on the same line as the code without "&"
Consider something like this (though I cannot check the logic of the bat):
setlocal EnableDelayedExpansion
setlocal enableExtensions
::queryex output file
sc queryex>services.TEMP
find /i /N "DISPLAY_NAME: Hotspot" services.TEMP>tmp1.TEMP
FOR /F "skip=2" %%G in (tmp1.TEMP) do (
set num=%%G
set num=!num:~1,3!
echo !num!>serviceList.TEMP
)
FOR %%X in (serviceList.TEMP) do (
call :subroutine %%G
)
del /S *.TEMP >>debug.txt 2>>debug.txt
exit /b %errorlevel%
:subroutine
setlocal enableDelayedExpansion
set /a skiplines=%~1+7
set "filter="skip=%skiplines%""
FOR /F %filter% %%Z in (services.TEMP) do (
call debug.cmd
set serv=%%Z
rem extract PID
set "serv=!serv: =!"
set "serv=!serv::=!"
set procID=!serv!
taskkill /pid !procID! /f >>debug.txt 2>>debug.txt
goto :break_for
)
:break_for
endlocal
exit /b
Should the > in your echo to serviceList.TEMP be a >> so that you append to the file?
echo !num!>>serviceList.TEMP
In which case, you should also ensure that the file is deleted prior to the appending operations.
Also, I assume you missed the /F from your FOR loop, as you're trying to read the lines of the serviceList.TEMP file, yes?
FOR %%X in (serviceList.TEMP) do (
Should be...
FOR /F %%X in (serviceList.TEMP) do (
?
Also, you can append to the same file with both std out and err by doing this...
someprocesshere 1> out.log 2>&1
I'm trying to read a file and output the lines of data into registry keys. The data collection works, but I don't understand the syntax required to increment the string values in the last loop.
#echo OFF
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq skip=1 delims=" %%a in (`"findstr /n ^^ C:\GetSID.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!" This removes the prefix
echo(!var:~76,63!>>C:\SIDoutput.txt
goto :EndLoop
)
:EndLoop
set /p SID= <C:\users\paintic\SIDoutput.txt
set KEY_NAME="HKEY_USERS\!SID!\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts"
set Counter=1
for /f %%x in (C:\users\paintic\Networkprinters.txt) do (
set "Line_!Counter!=%%x"
set /a Counter+=1
if !Counter!==3 (Echo %line_counter%)
)
set /a counter2=!counter!-3
set counter=1
The part below is what I can't get to work. I'm trying to write LINE_1, LINE_2 and LINE_3 values from the previous loop to increment via the loop below. So VALUENAME should equal LINE_1, TYPE should = LINE_2's value and DATA should = LINE_3 on the first run and keep going up by 1 until the loop finishes (end of the file read)
`for /L %%i in (1,1,%counter2%) do (
set ValueName=%Line_!counter!%
set /a counter+=1
set Type=%Line_!counter!%
set /a Counter+=1
set Data=%Line_!counter!%
set /a Counter+=1
echo !ValueName!
echo !Type!
echo !Data!
REG ADD %KEY_NAME% /v !ValueName! /t !Type! /d !Data! /f
)
ENDLOCAL
Pause`
On searching for errors in batch file it is always helpful to use in first line #echo on or remove #echo off or comment this line with rem to see what cmd.exe really executes.
Command line interpreter fails on lines with set VariableName=%Line_!counter!% as the interpreter does not know what to expand first. I think it is not possible to create dynamically the name of an environment variable and reference next the value of this environment variable. This approach most likely does not work ever.
However, what you want to achieve can be done much easier directly in second loop as the following example demonstrates:
#echo off
setlocal EnableDelayedExpansion
rem Create data for demo example.
set "KEY_NAME=HKEY_USERS\S-1-5-20\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts"
echo TestValue>"%TEMP%\Networkprinters.txt"
echo REG_SZ>>"%TEMP%\Networkprinters.txt"
echo Sample Data>>"%TEMP%\Networkprinters.txt"
echo AnotherValue>>"%TEMP%\Networkprinters.txt"
echo REG_DWORD>>"%TEMP%\Networkprinters.txt"
echo ^1>>"%TEMP%\Networkprinters.txt"
rem Now the loop follows which reads the data from the file line
rem by line and build the line for using command "reg.exe" to
rem add the data to registry of the user with the defined SID.
set Counter=1
for /f "usebackq delims=" %%x in ("%TEMP%\Networkprinters.txt") do (
if "!Counter!"=="1" (
set "ValueName=%%x"
) else if "!Counter!"=="2" (
set "ValueType=%%x"
) else (
set "ValueData=%%x"
rem Echo the command instead of really executing "reg.exe".
echo reg.exe ADD %KEY_NAME% /v "!ValueName!" /t !ValueType! /d "!ValueData!" /f
set Counter=0
)
set /a Counter+=1
)
rem Delete the text file created for demo example.
del "%TEMP%\Networkprinters.txt"
endlocal
This solution is much easier than what you have tried and can be maybe even more simplified.