I want to read a .txt file using batch script.
Each line should be stored in a variable.
My problem: I have to give the command a file path to the .txt file. Unfortunately this hasn't worked so far. The solution is probably very simple, but I haven't found it yet.
for /f "tokens=*" %%a in ("%FilePath%backup\packs.txt") do (
Set /a count+=1
Set url[!count!]=%%a
)
echo %url[2]%
for /f loops can process three different types of data - files, strings, and commands. Each of these is indicated differently when you call the for command.
A file is processed by not using quotes in the set area: for /f %%A in (file.txt) do (
A command is processed by using single quotes: for /f %%A in ('find "abc" file.txt') do (
A string is processed by using double quotes: for /f %%A in ("hello world") do (
Of course, sometimes you need to process a file with a space in the path, and that's when you'd use the usebackq option. This option will still process all three types of data, but the indicators will be different.
A file is processed by using double quotes: for /f "usebackq" %%A in ("some file.txt") do (
A command is processed by using backticks: for /f "usebackq" %%A in (`find "don't" file.txt`) do (
A string is processed by using single quotes: for /f "usebackq" %%A in ('19^" screen') do (
Either removing the quotes from your file path or adding the usebackq option will set the variables for you.
#echo off
setlocal enabledelayedexpansion
set "FilePath=.\test_path\"
set "count=0"
for /f "usebackq tokens=*" %%A in ("%FilePath%backup\packs.txt") do (
set /a count+=1
set "url[!count!]=%%A"
)
echo %url[2]%
Related
I need a batch script that will read in another batch script (batch2) and:
look for the string "configout:" OR "configin:"
If it encounters one of these two strings, extract what's after it until the string ".xml"
copy paste it in a new text file.
and do this for each line of batch2.
For exemple:
If this is my first line in the batch script
/configin:%faxml%fm_sellin_in.xml /configout:%faxml%transco_fm_sellin_out%col_transco%.xml /inputfile:
I should have this in my text file:
%faxml%fa_sellin_in.xml
%faxml%transco_fm_sellin_out%col_transco%.xml
I have seen a good code in Here:
for /f "tokens=1-2 delims=~" %%b in ("yourfile.txt") do (
echo %%b >> newfile.txt
echo removed %%a)
but i don't know how to adapt it to my specific case.
Why not replace all the /configin and /configout with newlines? -
(Replace string with a new line in Batch)
For example
setlocal EnableDelayedExpansion
set "str=/configin:%%faxml%%fm_sellin_in.xml /configout:%%faxml%%transco_fm_sellin_out%%col_transco%%.xml /inputfile:"
set str=!str:/configin^:=^
!
set str=!str:/configout^:=^
!
Now, !str! would contain
fm_sellin_in.xml
transco_fm_sellin_out.xml /inputfile:
Then, you could use the for loop to extract the strings
for /f "tokens=1,2 delims=. " %%a in ("!str!") do ()
this for loop iterates through each line and splits each line with the and . characters.
So %%a is your file name and %%b is the extension.
then
if [%%b]==[xml] (echo %%a.%%b>>mytextfile.txt)
We will do this for all the lines of batch2.
And the finished code is
setlocal EnableDelayedExpansion
for /f "delims=" %%c in (batch2.txt) do (
set str=%%c
set str=!str:/configin^:=^
!
set str=!str:/configout^:=^
!
for /f "tokens=1,2 delims=. " %%a in ("!str!") do (if [%%b]==[xml] (echo %%a.%%b>>mytextfile.txt))
)
I want to make a generic script which will convert a fixed width flat file into csv. Below is my approach:
`echo off
setlocal EnableDelayedExpansion
echo a,b,c>final.txt
for /f "tokens=1 delims=;" %%i in (source.txt) do (
set x=%%i
for /f "tokens=1,2 delims=," %%a in (config.txt) do (
call SET VAR=!x:~%%a,%%b!
for %%p in (!VAR!) do (echo/|set /p ="%%p,"
) >>final.txt
)
)
`
Config file which I am using contains the parameters for substring which states from where to do the substring and how many characters.
Config file contains:
0,9
9,3
12,11
23,7
30,1
31,1
32,5
37,9
46,9
55,3
58,9
67,9
76,9
85,9
94,1
Source file contains the actual fixed with source.
Now with my code I am getting the result but for the fields which has no value/empty in the source is not reflecting in the final output.
Example:
Source:
1234<space>678 [col1=678,col2=space,col3=678]
Output (Current):
1234,678
Output(Expected):
1234,,678
Please help
Your for %%p in (!VAR!) do (…) loop executes defined (…) command for all strings found in !VAR! delimited with white space(s). So if !VAR! results to all white spaces, then consequential for %%p in ( ) do (…) loop executes nothing. Next code snippet could help:
echo off
setlocal EnableDelayedExpansion
echo a,b,c>final.txt
rem replace the €€€ string with any unused one
set "fooString=€€€"
for /f "tokens=1 delims=;" %%i in (source.txt) do (
set "x=%%i"
for /f "tokens=1,2 delims=," %%a in (config.txt) do (
call SET "VARraw=!x:~%%a,%%b!%fooString%"
rem replaced with respect to the OP's comment: for %%p in (!VARraw!) do (
for /F "tokens=*" %%p in ("!VARraw!") do (
set "rav=%%p"
set "var=!rav:%fooString%=!"
echo/|set /p "=!var!,"
) >>final.txt
)
)
Edit: note that for /F "tokens=*" %%p in ("!VARraw!") do ( would remove leading spaces from the !VARraw! string.
This is my first posting so if the format is not as it supposed to be please excuse me for this. (Suggestions for
improvement are welcome.)
I am trying to create a batchfile that will read last lines from logfiles and copy them to a new file.
Until now I have found here a way to read the last line.
Code would be something like:
for /f %%i in ('find /v /c "" ^< someFile.txt') do set /a lines=%%i
set /a startLine=%lines% - 1
more /e +%startLine% someFile.txt > lastLines.txt
The above code works for one file at a time. What I need is to read the last line from all files in a known list and add this line to a new .csv file.
I have been using the following code for getting the 4th entry in the logfiles but it returns every line of every logfile:
for /f %%x in (%list%) do for /f "delims=.txt, tokens=4" %%i in (%%x.txt) do echo %%x, %%i >> output.csv
What I would need is a sort of combination of both but I don't know how to combine them and make the complete last line be copied to the .csv file.
===
#Magoo:
Thanx for your reaction.
In every logfile can be 1 to >100 lines with comma separated information. Something like:
"LOGON,6-1-2015,12:43:39,USERNAME,HOSTNAME,,,,192.168.209.242,00:21:5A:2E:64:5E"
The last code with the 4th entry was used to get a list of all accounts that had logged in to the computers. This code gave me a very large list of all logon/logoff events on all computerlogs I checked in %list%.
In %list$ I had all the names of logfiles I wanted to be checked. This returned all lines.
For a new batchfile I need only the last logon/logoff entry and I want the whole last line.
So I have a .txt file with the hostnames of all computers I need to examine.
This .txt file will be read line by line via the variable %list%.
From every logfile I need only the last line copied to an output file.
===
I just tried the solution offered by JosefZ. Unfortunately this does not work for me yet. No lastlines are copied to the resultfile. In the code I removed the extra entry for possible lastlines for there are no empty lines in the logs, I also added an entry for the hostname I want to be available in the result. JosefZ had the filename there:
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set "host=%%~x"
for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
set "filename=.\logs\%filename:&=^&%.txt"
echo %host%,%lastline%>>output.csv
goto :eof
The resultfile shows only the hostnames. I'll puzzle some more with this but all tips are welcome!
===
Got it!!!
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set filename= :: *empty previous filename*
set lastline= :: *empty previous lastline*
set "host=%%~x"
set "filename=.\logs\%host%.txt" :: *creating the filename from path+hostname+extention*
for /F "tokens=*" %%G in ('type "%filename%"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
echo %host%,%lastline%>>output.csv
goto :eof
Your approach with line numbering could fail if a file has more trailing empty lines. Fortunately for /F loop ignores (does not iterate) empty lines; let's put to use this feature: in the script used next practices:
disabledelayedexpansion to allow ! in file names
set "list=_listing.txt" where the _listing.txt contains list of file names (full path and extension .txt including), one file name on one line: got by dir /b /s *.txt>_listing.txt
type nul>files\output.csv to empty the output file (optional)
set "lastline=!!!file empty!!!" to initialize variable %lastline%; could be set "lastline=" as well
call :lline to process variables %filename% and %lastline%
set "filename=%filename:&=^&%" to allow & in file names
The script is as follows:
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>files\output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set "filename=%%~x"
set "lastline=!!!file empty!!!"
rem the whole line
for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"
rem the fourth token only
rem for /F "tokens=4" %%G in ('type "%%~x"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
set "filename=%filename:&=^&%"
echo %filename% %lastline%
rem >>files\output.csv
goto :eof
Sample _listing.txt file:
d:\bat\files\1exclam!ation.txt
d:\bat\files\2exc!lam!ation.txt
d:\bat\files\11per%cent.txt
d:\bat\files\12per%cent%.txt
d:\bat\files\17per%Gcent.txt
d:\bat\files\18per%%Gcent.txt
d:\bat\files\21ampers&nd.txt
d:\bat\files\22ampers&&nd.txt
Output:
d:\bat>lastlines
d:\bat\files\1exclam!ation.txt 0 15.01.2015 1:52:28.48 -15072 20465
d:\bat\files\2exc!lam!ation.txt 6 15.01.2015 1:52:28.50 3250 16741
d:\bat\files\11per%cent.txt -8 15.01.2015 1:52:28.50 -3692 27910
d:\bat\files\12per%cent%.txt !!!file empty!!!
d:\bat\files\17per%Gcent.txt 0 15.01.2015 1:52:28.56 14508 12374
d:\bat\files\18per%%Gcent.txt 1 15.01.2015 1:52:28.56 30540 26959
d:\bat\files\21ampers&nd.txt 15.01.2015 1:22:50.18
d:\bat\files\22ampers&&nd.txt 15.01.2015 1:22:50.18
Honestly, all that ballast is for (possibly) trailing empty lines in files and for (possibly) ! and & in file names only; all could be done with
for /f %%x in (%list%) do for /f "skip=%startLine% tokens=4" %%i in (%%x) do echo %%x, %%i >> output.csv
You should use a simple FOR to iterate a list of values, not FOR /F.
Something like the following should work:
#echo off
setlocal enableDelayedExpansion
>>output.csv (
for %%F in (
"file1.log"
"file2.log"
"file3.log"
etc.
) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
more +!skip! %%F
)
)
The quotes around the file names are there in case you get a name with spaces.
You could use your LIST variable if it looks something like
set LIST="file1.log" "file2.log" "file3.log" etc.
#echo off
setlocal enableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.
>>output.csv (
for %%F in (%LIST%) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
more +!skip! %%F
)
)
If any of your file names contain the ! character, then you must toggle delayed expansion ON and OFF within your loop. Otherwise the delayed expansion will corrupt the names when %%F is expanded.
#echo off
setlocal disableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.
>>output.csv (
for %%F in (%LIST%) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
setlocal enableDelayedExpansion
more +!skip! %%F
endlocal
)
)
pleas help.
SET "prog=C:\Program Files (x86)\Common Files\Adobe"
SET "file=%prog%\Color\Profiles\%Value%"
FOR /f %%i IN ("%file%") DO (
ECHO filename=%%~ni
ECHO path=%%~fi
pause
)
Result:
filename=Program
path=C:/Program
I need path=C:\Program Files (x86)\Common Files\Adobe\Color\Profiles\%Value%
and filename %Value% no Program...
Thx.
The FOR /F command as you wrote it is designed to process A STRING enclosed in quotes. This way, the following command:
FOR /f %%i IN ("%file%") DO (
place in %%i variable the first token of such string ("C:\Program") and %%~ni tries to extract a file name from such string!
If you want to extract the name of the file, you should use a plain FOR command with NO /F option:
FOR %%i IN ("%file%") DO (
ECHO filename=%%~ni
ECHO path=%%~fi
pause
)
What I tried to mean is that in this case you want to process the %file% variable contents as a file name, NOT as a string, so you should use a plain FOR command designed to process files (instead FOR /F designed to process strings).
If you change your FOR line to this, you'll get results closer to what you want:
FOR /f "DELIMS=" %%i IN ("%file%") DO (
OR
FOR /f "TOKENS=*" %%i IN ("%file%") DO (
The specified TOKENS and DELIMS parsing options allow the FOR to accept the whole string from %file% into %i and ignore spaces. Source: http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/for.mspx?mfr=true
I need to get all the filenames in a directory and store them in some variable from a command line.
I came across this
`dir /s /b > print.txt`
but this prints the file names to a txt file.
How can I store these names in a variable?
I'm assuming you really mean Windows batch file, not DOS.
Batch environment variables are limited to 8191 characters, so likely will not be able to fit all the file paths into one variable, depending on the number of files and the average file path length.
File names should be quoted in case they contain spaces.
Assuming they fit into one variable, you can use:
#echo off
setlocal disableDelayedExpansion
set "files="
for /r %%F in (*) do call set files=%%files%% "%%F"
The CALL statement is fairly slow. It is faster to use delayed expansion, but expansion of %%F will corrupt any value containing ! if delayed expansion is enabled. With a bit more work, you can have a fast and safe delayed expansion version.
#echo off
setlocal disableDelayedExpansion
set "files=."
for /r %%F in (*) do (
setlocal enableDelayedExpansion
for /f "delims=" %%A in ("!files!") do (
endlocal
set "files=%%A "%%F"
)
)
(set files=%files:~2%)
If the file names do not fit into one variable, then you should resort to a pseudo array of values, one per file. In the script below, I use FINDSTR to prefix each line of DIR ouptut with a line number prefix. I use the line number as the index to the array.
#echo off
setlocal disableDelayedExpansion
:: Load the file path "array"
for /f "tokens=1* delims=:" %%A in ('dir /s /b^|findstr /n "^"') do (
set "file.%%A=%%B"
set "file.count=%%A"
)
:: Access the values
setlocal enableDelayedExpansion
for /l %%N in (1 1 %file.count%) do echo !file.%%N!
As #Matt said, use a batch file.
setlocal enabledelayedexpansion
set params=
for /f "delims=" %%a in ('dir /s/b') do set params=!params! %%a
setlocal enableDelayedExpansion
set /a counter=0
for /f %%l in ('dir /b /s') do (
set /a counter=counter+1
set line_!counter!=%%l
)
set line_
If you want to store all in one variable check this:
Explain how dos-batch newline variable hack works