I have a file.txt that contains the paths of the oracles that installed on my machine.
from the registry
example this file contains:
ORACLE_HOME REG_SZ C:\oracle\product\11.2.0\dbhome_1
ORACLE_HOME REG_SZ C:\oracle\product\11.2.0\dbhome_2
I want via my batch file to insert all the paths of the oracles into a list or something like list.
How can I do it in batch file?
thanks!
Assuming you want a "list" of values in memory, not in a file:
I think most people prefer an "array" of values that can be accessed via an index value. (Note - batch does not have formal arrays, but they can be emulated).
The following simple code works great as long as none of the home paths contain !. Expansion of %%B will be corrupted if it contains ! and delayed expansion is enabled.
#echo off
setlocal enableDelayedExpansion
:: Read the file and create an "array" of home paths
:: This will fail if any of the paths contain !
set /a cnt=0
for /f "usebackq tokens=2*" %%A in ("file.txt") do (
set /a cnt+=1
set "home.!cnt!=%%B"
)
:: Access the "array" members
for /l %%N in (1 1 %cnt%) do echo !home.%%N!
You could probably run the above code for years in many environments and never run into a problem. But someone somewhere might include ! in the Oracle home path. There are a number of strategies to fix the above to deal with !. Below are three options:
Option 1 - The least amount of code, but the slowest due to CALL
#echo off
setlocal disableDelayedExpansion
:: Read the file and create an "array" of home paths
:: This will safely process all paths, regardless of value
set /a cnt=0
for /f "usebackq tokens=2*" %%A in ("file.txt") do (
set /a cnt+=1
call set "home.%%cnt%%=%%B"
)
:: Access the "array"
setlocal enableDelayedExpansion
for /l %%N in (1 1 %cnt%) do echo !home.%%N!
Option 2 - An interesting and efficient method using FINDSTR to count the rows.
#echo off
setlocal disableDelayedExpansion
:: Read the file and create an "array" of home paths
:: This will safely process all paths, regardless of value
set /a cnt=0
for /f "tokens=1,3* delims=: " %%A in ('findstr /n "^" "file.txt"') do (
set "home.%%A=%%C"
set "cnt=%%A"
)
:: Access the "array" members
setlocal enableDelayedExpansion
for /l %%N in (1 1 %cnt%) do echo !home.%%N!
Option 3 - An efficient method that uses delayed expansion toggling, but the most code
#echo off
setlocal disableDelayedExpansion
:: Read the file and create an "array" of home paths
:: This will safely process all paths, regardless of value
set /a cnt=0
for /f "usebackq tokens=2*" %%A in ("file.txt") do (
set /a cnt+=1
setlocal enableDelayedExpansion
for %%N in (!cnt!) do (
endlocal
set "home.%%N=%%B"
)
)
:: Access the "array"
setlocal enableDelayedExpansion
for /l %%N in (1 1 %cnt%) do echo !home.%%N!
It is also possible to have a list of home paths in a single variable. Each path should be enclosed by quotes. The paths could be delimited by space, comma, semicolon, equal, or tab. I chose space.
The size of the list is limited because the maximum size of a batch environment variable is ~8191 bytes. This solution is also relatively slow due to the CALL. Neither of these issues are likely to be a problem in the real world.
#echo off
setlocal disableDelayedExpansion
:: Read the file and create a space delimited list of quoted home paths
:: This will safely process all paths, regardless of value
for /f "usebackq tokens=2*" %%A in ("file.txt") do (call set list=%%list%% "%%~B")
:: optional - remove leading space
(set list=%list:~1%)
:: Display the list
echo list=%list%
:: Access the list members
for %%F in (%list%) do echo %%~F
for /f "tokens=3 delims= " %%a in (file.txt) do echo %%a >>paths.txt
Related
I have a .txt file which contains 1 line in the following format:
XX-C-0001
I want to save a new file with the incremented number, like:
XX-C-0002
The Problem is, I dont know how to save the "0002" as a variable
Heres what i come up with:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /f "tokens=3" "delims=-" %%a in name.txt(
'VER'
) do (
set myvar=%%a
)
set /A var=%myvar%+1
>new_name.txt echo %var%
pause
endlocal
Check your for syntax (it's off at some points, but where did 'ver' come from?)
To increase the number, you have to be a bit more creative because of the leading zeros. Put a 1 in front of it (make it 1000x), then increase it and use just the last four characters for the result.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /f "tokens=3 delims=-" %%a in (name.txt) do set "myvar=1%%a"
set /A myvar+=1
>new_name.txt echo XX-C-%myvar:~-4%
type new_name.txt
endlocal
What I want to achieve is have an output file that lists how many files are in a specific folder on a number of different remote machines ie(127.0.0.1 394files).
The issue I'm having is the output file generated only has 1 line in it, the last IP in ip.txt
To try and explain the code below, I'm creating a variable called 'testip' which should match the ip/machine I'm calling from ip.txt , this is created purely for the echo at the end, when I tried calling %%i or %%b at an echo, all that appears in the text file is %i or %b , as if its truncating 1 of the % characters. creating a separate variable (SET testip=%%b) got around that issue.
Next loop, it looks for the IP list in the ip.txt file and performs a count on the \test_scripts\ folder.
Then it should echo the IP it ran as well as the count number.
Any idea where this is going wrong?
Any feedback appreciated.
#ECHO OFF
SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION
for /f "delims=" %%b in (' type "C:\Users\testuser\Desktop\test_scripts\ip.txt" ' ) DO SET testip=%%b
for /f "delims=" %%i in (' type "C:\Users\testuser\Desktop\test_scripts\ip.txt" ' ) DO (
SET count=0
for %%o IN ('type "\\%%i\c$\Users\testuser\Desktop\test_scripts\*.*" ' ) DO (
SET /A count=count + 1
)
)
echo %testip% %count% >> output.txt
ENDLOCAL ENABLEDELAYEDEXPANSION
ENDLOCAL
Try this one instead. Note how delayed expansion is used. For more on the commands, run them with /? switch on cmdline. for instance. for /?
Also you will see that command type is not used at all.
#echo off
setlocal enabledelayedexpansion
set "location=C:\Users\testuser\Desktop\test_scripts\ip.txt"
for /f "delims=" %%i in (%location%) DO (
set "remote=\\%%i\c$\Users\testuser\Desktop\test_scripts\*"
set count=0
for %%x in (!remote!) do set /a count+=1
echo !remote! !count! >> output.txt
)
This is the same method as Gerhards answer but with two modifications. I've set the remote variable at the start of the script instead of repeating that on each iteration of the loop; and I'm outputting the IP address, instead of the remote path, with the file count.
#Echo Off
SetLocal EnableDelayedExpansion
Set "location=%UserProfile%\Desktop\test_scripts\ip.txt"
Set "remote=\\%%A\C$\Users\testuser\Desktop\test_scripts"
( For /F "Usebackq Delims=" %%A In ("%location%") Do (Set "#=0"
For %%B In ("%remote%\*") Do Set /A #+=1
Echo %%A !#!))>"output.txt"
This is similar except that it uses the Dir command to retrieve the file count. The Dir command can take account of hidden and system files etc.
#Echo Off
SetLocal EnableDelayedExpansion
Set "location=%UserProfile%\Desktop\test_scripts\ip.txt"
Set "remote=\\%%A\C$\Users\testuser\Desktop\test_scripts"
( For /F "Usebackq Delims=" %%A In ("%location%") Do (Set "_=" & Set "#="
For /F %%B In ('Dir "%remote%" /A-D/D') Do Set "#=!_!" & Set "_=%%B"
Echo %%A !#!))>"output.txt"
You can easily modify your location and remote paths on lines 3 and 4, ensuring that the \\%%A\ section remains unaltered.
In have not tested either script, nor have I made any attempt at error trapping etc. I'll leave that to you, should it be required.
Here is my code for storing the words extracted from a log file into an array, which I want to use in the batch file later on.
cls
#echo off
set /a i=0
TIMEOUT 2
REM I want to save the words from newlog.txt into an array for later use in batch file.
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=1,2,3 delims= " %%G IN (newlog.txt) DO ( set a[%i%]=%%H
& set /a i+=1 #echo !a[%i%]! )
#echo %i%
#echo a[%i%]
TIMEOUT 200
I just want to use them as global variables.
#echo off
set /a i=0
REM I want to save the words from newlog.txt into an array for later use in batch file.
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=1,2,3 delims= " %%G IN (q48428047.txt) DO (
set a[!i!]=%%H&set /a i+=1)
SET a[
pause
GOTO :EOF
I used a file named q48428047.txt containing some dummy data for my testing.
Note that %i% will be replaced by the value of i *as it was when the *forwas encountered that is, 0.
Your second set within your parentheses is incorrect. It's missing the & before the #echo. Also, you appear to be attempting to increment i and then show the corresponding array entry, which makes no sense because you haven't yet stored anything in that array-entry, you've attempted to install it in the previous position. It won't work anyway, because %i% will be replaced by 0, not the varying value of i.
And whereas you may get the count-of-lines appearing on the screen, a[numlines] will not be defined.
Use pause to stop the batch for perusal. Preferably, run the command from the prompt, not by clicking.
The modified code reads each line of the file putting the first word in %%G, second in %%H and third in %%I. it then assigns %%H to a[currentlinenumber] and increments the line number in i.
The set a[ will display all environment variables whose names start with a[.
In addition to the answer already provided, if you really have a need to Echo each variable value immediately after it is Set then you would need to invoke a Call command:
#Echo Off
Rem Undefine any existing variables which begin with a[
For /F "Delims==" %%A In ('"(Set a[) 2>Nul"') Do Set "%%A="
Set "i=0"
ClS
SetLocal EnableDelayedExpansion
For /F "UseBackQ Tokens=2 Delims= " %%A In ("newlog.txt") Do (
Set "a[!i!]=%%A"
Call Echo "%%a[!i!]%%"
Set /A i+=1
)
If %i% GEq 1 Echo(&Echo %i% variables were defined&Echo(
(Set a[) 2>Nul
Timeout 200
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
)
)
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