Batch script issue for getting dynamic column of csv file? - windows

This is script which i am using for export the data from csv and write into a .trn extension file. The code execute for certain column of csv file data right, i mean to say if the column no indexing A to Z, code execute right,but when after the Z column means for AA,AB ect the data gets wrong. Code you can see here:
Batch Script
#echo off
set "line1=^%%a,cf,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,,,,,,,,,,,,,"
set "line2=^%%a,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,qbconid,,,^%%b,,,,,,,,,"
.......................................................................................
.......................................................................................
set "line26=^%%a,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,txtstate,,,^%%z,,,,,,,,,"
set "line27=^%%a,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,pmtper,,,^%%aa,,,,,,,,,"
set "line28=^%%a,#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,minfee,^%%ab,,,,,,,,,"
(for /F "tokens=1-28 skip=1 delims=," %%a in ('type "NewPortfolios.csv"') do (
echo %line1%
echo %line2%
............
............
echo %line26%
echo %line27%
echo %line28%
)) >"file.trn"
And the csv file data is:
A B C AA AB
$portcode $qbconId $name ....... $pmtper #minfee
asingh12 123456789 Ajay Singh....... ajay 123
Output is:
asingh12,cf,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,,,,,,,,,,,,,
asingh12,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,qbconid,,,123456789,,,,,,,,,
...................................................................................
asingh12,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,pmtper,,,asingh12a,,,,,,,,,
asingh12,#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,minfee,asingh12b,,,,,,,,,
In the above 2 lines you can see that the column value is coming wrong.
As you can see CSV data the last 2 column value should be ajay and 123 but it is coming as asingh12a and asingh12b.These are the values of a and b.It should come from AA and AB.
Can someone please help me in this.?
**EDITED HERE**
Hi Aacini - Hope you are doing well. I am facing again an issues with .csv file convert in to .txt file. Now this time getting a data from .csv with Quotes(") that's why the batch script is not running properly. Please find the sample data from .csv in to .txt format-
"_portcode","_qbconId","_name","_address","_city","_state","_zip","_bmeth","_ffee","_brak1","_rate0","_brak2","_rate1","_brak3","_rate2","_brak4","_rate3","_brak5","_rate4","_rate5","_bre","_custact","_custody","_qbmgrid","_refby","_txstate","_pmtper","_minfee"
"schorira","001c000000WtrL1AAJ",,"9232 Collegeview Cir","Bloomington","MN","55437","T",,"1000000.0","1.25",,,,,,,,,"1.0","Robert M. Schofield IRA Rollover",,"Schwab","JTB","Patrick Stephens","MN","Quarterly","0". Previous time in .csv data there is no Quotes. Please help me out. If you want more clarification from my side please let me know. I appreciate your help in advance.
Hi Acini,
Till now we are waiting for your reply. Please help me out.

EDIT: I fixed a couple details, it should correctly run now.
EDIT #2: Subtle bug fixed, and an example added
#echo off
set "letter=abcdefghijklmnopqrstuvwxyz"
set "line1=!a!,cf,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,,,,,,,,,,,,,"
set "line2=!a!,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,qbconid,,,!b!,,,,,,,,,"
set "line26=!a!,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,txtstate,,,!z!,,,,,,,,,"
set "line27=!a!,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,pmtper,,,!aa!,,,,,,,,,"
set "line28=!a!,#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,minfee,!ab!,,,,,,,,,"
setlocal EnableDelayedExpansion
(for /F "usebackq skip=1 delims=" %%a in ("NewPortfolios.csv") do (
set i1=0
set "line=%%a"
for %%b in ("!line:,=" "!") do for /F "tokens=1,2" %%i in ("!i1! !i2!") do (
if %%i lss 26 (
set var=!letter:~%%i,1!
) else (
set var=a!letter:~%%j,1!
)
set "!var!=%%~b!
set /A i1+=1, i2=i1-26
)
echo %line1%
echo %line2%
echo %line26%
echo %line27%
echo %line28%
)) > file.trn
Previous Batch program can output up to a maximum of 52 columns (a..z aa..az), but it is very easy to increment this range. With this input data:
A, B, C, D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z, AA, AB
$portcode,$qbconId,$name, D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$pmtper,#minfee
asingh12,123456789,Ajay Singh,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,ajay,123
the output is:
asingh12,cf,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,,,,,,,,,,,,,
asingh12,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,qbconid,,,123456789,,,,,,,,,
asingh12,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,txtstate,,,Z,,,,,,,,,
asingh12,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,pmtper,,,ajay,,,,,,,,,
asingh12,#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,y,minfee,123,,,,,,,,,

Related

Remove Commas in CSV without adding extra columns

I have this script intended to remove "extra commas" within a string in a CSV.
#echo off & setlocal EnableDelayedExpansion
echo Removing commas from FILE CSV file...
type nul > "H:\CONVERT_CSV.csv"
for /F "delims=" %%i in ('type "H:\FILE.csv"') do (
set row=%%i
set row=!row:"=!
echo.!row!>> "H:\CONVERT_CSV.csv"
)
But my script, instead of removing the comma, it adds an extra field within that record.
I know the problem sits in the set row!row"=! line, but I can not figure out what.
Please help
Example
From this:
Column A,Column B
Now,All,2
Then,After
To this:
Column A,Column B
Now,All 2
Then,After
EDIT: EXTRA INFO:
the csv has:
123 ,the time, "Gone, For good", 2023
Then it should become:
123 ,the time, "Gone For good", 2023

Win Batch nested for returns "unexpected" error

Win10, CMD.
Working on a long, complicated script, and hit a part that just does not want to cooperate. Here's a snippet that illustrates the problem:
set TESTSTR="abc def ghi jkl mno pqr stu vwx yz"
for /l %%a in (1,1,9) do (
set I=%%a
for /f "tokens=!I!" %%b in ("%TESTSTR%") do echo %%b
)
The expected result would be
abc
def
ghi
jkl
mno
pqr
stu
vwx
yz
But I just get 9x of this:
!I!" was unexpected at this time.
I've tried multiple variants of this, including set VAR="tokens=%%a" - for /f !VAR! ... I've stuck various echos in there and found that the variable %%a is incrementing properly and any intermediate vars I try to use are being set correctly.
It just doesn't seem to be able to use a delayed expansion or loop variable in the options section of another loop. I've done similar pre-loop options definitions and they normally work just fine, but never tried it in nested for's, using the outside loop's variable as a parameter for the inside loop like this.
Example: this code snippet works, showing only directories named "Update??" in the current dir (yes, I know that's way more than would be needed, I just grabbed it and repurposed it for this demo - the original code had a set rather than echo, with the intent of grabbing the most recent directory):
set FORPARM="usebackq tokens=1"
for /f %FORPARM% %%f in (`dir /b /a:d /o:d Update??`) do echo %%f
This example is not inside a for or other situation that would require delayed expansion, which I think is causing issues with the problem code above - the for command just doesn't seem to be able to handle delayed expansion or for variables as part of its command.
I suppose I could do it with call, putting the first for's var as a parameter to the call, and the call has the inner for, but would prefer not to - the routine I pulled this from is complex enough already - it reads a data file and populates multiple arrays. I have a variant of that routine that works, but it's pretty kludgey & requires editing when the number of arrays changes in the data file. I'm trying to speed it up, make it neater, and not require code alteration when the data alters.
Anyone else ever seen and gotten past this one?
You were very close with your code.
The inner for-loop needs the updated value from the outer for-loop in it's for parameter.
This can be done by moving the inner for-loop to a subroutine and call this subroutine.
In the code below I have changed the inner for-loop to a single-line subroutine.
This keeps the code very close to yours.
#echo off
set TESTSTR="abc def ghi jkl mno pqr stu vwx yz"
for /l %%a in (1,1,9) do (
cmd/c "#echo off&for /f "tokens=%%a" %%b in (%TESTSTR%) do echo %%b"
)
I don't really consider this THE answer, but it is AN answer, based on what I was trying to avoid (and #OJBakker's answer). Putting this here instead of a comment because the comment just munges the code sections - I probably just don't know what I'm doing there yet...)
With the code as:
:nested_for_test
set TESTSTR=abc def ghi jkl mno pqr stu vwx yz
for /l %%a in (1,1,9) do (
call :nested_for_test_inner %%a
)
exit /b
:nested_for_test_inner
for /f "tokens=%1" %%b in ("%TESTSTR%") do (
echo %%b
)
exit /b
Yes, I know the "do" sections do not need to be parenthecated - they are that way because the "real" code has a lot more than just a single line in each do...
The results are as expected:
Start: 8:28:05.98
abc
def
ghi
jkl
mno
pqr
stu
vwx
yz
Start: 8:28:05.98
Stop: 8:28:07.76
Elapsed: 1.78 seconds
Yes, I have a timer routine in my test file. This shows slower than I'd hoped, but within reason, considering the extra call.
If someone figures out how to do it without that call, please add!
Okay... To clarify the issue. Here's the original "kludgey" code - actual code, not a simplified illustrative sample (I left my comments to explain what it's doing):
:: 'call :array_load pathname [arry:val]'
:: INPUT - 1-2 parameters: datafile path and optional condition
:: RESULT - sets up arrays & UBOUNDs (array[0])
:: Read a datafile (identified in the first parameter). This file has an array
:: definition line and a number of data lines. The array definition line starts
:: with 'arry ' and lists the arrays to be populated from the data statements.
:: Data statements list the information to be put into the arrays, in the same
:: order as the arrays listed in the arry statement.
:: An optional second parameter causes only lines that have the value given for
:: that array to be included (ex: 'ZIP:23456' causes only addresses in zipcode
:: 23456 to be read).
:: The arry statement can be anywhere in the file. The data statements are read
:: in the order of appearance.
:: The Upper boundary (UBOUND) is stored in [0]
:array_load
set _DATAFILE=%1
set _COND=%2
if not exist %_DATAFILE% (
echo [E] - {array_load} Array datafile %1 not found. Aborting run.
pause
exit
)
:: Detect and set up for use of the second parameter.
if defined _COND for /f "tokens=1-2 delims=:" %%a in ("%_COND%") do (set _ARY=%%a&set _VAL=%%b)
:: Gets the list of arrays from the "arry" statement
for /f "usebackq tokens=1,*" %%a in (`findstr "^arry " %_DATAFILE%`) do ( set "ARRAYLIST=%%b")
:: Set up the array names and prep for the second loop. The "tokens" var sets
:: up to read the columns in the data statements. Token 1 is always "data" and
:: is skipped.
set ndx=1
for %%a in (%ARRAYLIST%) do (
set COL!ndx!=%%a
set /a ndx+=1
)
:: "TOKENS" is not a mathematical calculation - it is a range definition used
:: in the next FOR statement. Do not add /a to the set!
set TOKENS=2-%ndx%
set /a ARYCOUNT=ndx-1
:: Read the data statements into the arrays. The "if defined" increments the
:: index for the next read only if there is no condition or the condition is
:: met. The "for" inside this "if" exists because the condition can't be tested
:: without it.
set ndx=1
for /f "usebackq tokens=%TOKENS%" %%a in (`findstr "^data " %_DATAFILE%`) do (
set !COL1![!ndx!]=%%a
if %ARYCOUNT% GEQ 2 set !COL2![!ndx!]=%%b
if %ARYCOUNT% GEQ 3 set !COL3![!ndx!]=%%c
if %ARYCOUNT% GEQ 4 set !COL4![!ndx!]=%%d
if %ARYCOUNT% GEQ 5 set !COL5![!ndx!]=%%e
if %ARYCOUNT% GEQ 6 set !COL6![!ndx!]=%%f
if %ARYCOUNT% GEQ 7 set !COL7![!ndx!]=%%g
if defined _COND (
for /f "usebackq" %%x in (`echo %_ARY%[!ndx!]`) do set RES=!%%x!
if !RES!==%_VAL% set /a ndx+=1
) else (
set /a ndx+=1
)
set /a !COL1![0]=!ndx!-1
if %ARYCOUNT% GEQ 2 set /a !COL2![0]=!ndx!-1
if %ARYCOUNT% GEQ 3 set /a !COL3![0]=!ndx!-1
if %ARYCOUNT% GEQ 4 set /a !COL4![0]=!ndx!-1
if %ARYCOUNT% GEQ 5 set /a !COL5![0]=!ndx!-1
if %ARYCOUNT% GEQ 6 set /a !COL6![0]=!ndx!-1
if %ARYCOUNT% GEQ 7 set /a !COL7![0]=!ndx!-1
)
exit /b
This routine loads a set of index-correlated arrays. Here's an example data file. I left the comments in the file to help explain what's going on. Only the "arry" and "data" lines are actually used by the routine.
To be REFERENCED by :array_load function
The line starting with "arry " contains the names of the arrays to be
filled from the data provided. Columns do not need to line up; extra spaces
are ignored. There is a maximum of six arrays without revisiting the
:array_load functions. ANY change of the "arry" names requires revisiting
the code that uses them!
All Data lines must begin with "data ", and NO other lines can start that
way! The keywords "data" and "arry" are case-sensitive and must be followed
by a space.
All lines that do NOT start with "arry " or "data " are comments.
arry FIRST LAST PHONE ZIP
data Joe Wilson 202-417-2742 20122
data John Doe 209-659-2482 10523
data Susan Doe 209-659-2482 10523
data Bill Johnson 619-384-2582 53737
data Cindy Wahler 301-724-7496 20933
data Rebecca Tannis 410-473-2748 20536
This will result in FIRST[0]=6, FIRST[1]=Joe, LAST[0]=6, LAST[1]=Wilson, etc
on up to FIRST[6]=Rebecca ... ZIP[6]=20536 (all the [0]'s = 6, as the array size)
The code above works (and is reasonably fast), unless the last line is excluded by the condition check, in which case the last line is not actually excluded. It also must be edited if the number of arrays exceed the number of if ... geq .. %%... statements.
I'd like to: 1) fix the last line exclusion bug, 2) remove the many IFs for array count flexibility, 3) make it faster.
This is what I'm tinkering with now. It does #2, I expect it to do #1 when I get that part worked out, but it fails miserably on #3 - FAR slower. On this computer, it takes 20-30 seconds to process this list of just 6 values for only 4 arrays - my actual data files are about 110 lines with 7 values each and 21 lines of 5 each.
:array_load
set _DATAFILE=%1
set _FILTER=
if not exist %_DATAFILE% (
echo [E] - {array_load} Array datafile %1 not found. Aborting run.
pause
exit /b
)
if not "%2"=="" set _FILTER=%2
:: Gets the list of arrays from the "arry" statement
for /f "usebackq tokens=1,*" %%a in (`findstr "^arry " %_DATAFILE%`) do ( set "ARRAYLIST=%%b")
:: Set up the array names and prep for the second loop.
set ndx=1
for %%a in (%ARRAYLIST%) do (
set COL[!ndx!]=%%a
set /a ndx+=1
)
set /a ARYCNT=ndx-=1
:: Token 1 is always "data" and is skipped.
set ndx=1
for /f "usebackq tokens=1,*" %%a in (`findstr "^data " %_DATAFILE%`) do (
set _LN=%%b
for /l %%x in (1,1,%ARYCNT%) do (
set ARY=!COL[%%x]!
call :array_load_inner %%x
)
set /a ndx+=1
)
exit /b
:array_load_inner
for /f "tokens=%1" %%z in ("!_LN!") do set !ARY![!ndx!]=%%z
set /a !ARY![0]=!ndx!
exit /b
So, does this make your eyes cross as it does mine? :)
Either routine above is an "answer", just not the one I'm after - the first is my starting point, and works to the extent of the original question, which did not include references to arrays or inclusions. The second is far too slow to be viable. #Stephan answer would work if I weren't dealing with arrays. Apologies for putting this material into an "Answer" block - it's far too large for a comment (I guess I should have included original full code from the beginning, rather than try to keep the sample code at the "smallest common denominator", so to speak). Sorry...
EDIT completely changed due to new information.
Please try this new code. I guess it won't get much faster using batch.
As %_VAR% isn't used, you could simplify your second parameter (and skip disassembling %_COND%)
#echo off
setlocal enabledelayedexpansion
set "file=%~1"
set "_COND=%~2"
if not defined file goto :eof
for /f "tokens=1* delims=:" %%a in ("%_COND%") do (
set "_VAR=%%a"
set "_VAL=%%b"
)
rem set _
echo Start: %time%
REM get field names:
for /f "tokens=1*" %%A in ('findstr /b "arry " "%file%"') do (
set cnt=-1
for %%C in (%%B) do (
set /a cnt+=1
set "%%A[!cnt!]=%%C"
)
)
REM get Data-Array:
set "cnt=0" & REM number of data sets
for /f "tokens=1*" %%A in ('findstr /brc:"data .*%_VAL%\>" %file%') do (
set /a cnt+=1
set "cnt2=-1" & REM number of entries in the dataset
for %%C in (%%B) do (
set /a cnt2+=1
call set "%%arry[!cnt2!]%%[!cnt!]=%%C"
call set /a %%arry[!cnt2!]%%[0]=cnt
)
)
echo End: %time%
set |find "["
echo there are entries 0 to %cnt%.
Things that speed it up:
filtering the input (less lines to process)
no IF's at all
works even with empty %_VAL% so no need to check it each iteration of the loop
Possible contras:
filterstring is case sensitive (can be changed with findstr's /i parameter, but would also make the keyword data case insensitive.
Possibly false positives (John / Johnson is no probem because of the word-boundary \>, but JohnJohn would be found with the John filter (Johnjohn wouldn't))
I very much hope the 5-token datasets and the 7-token datasets are in different files
There is no hardcoded limit for the tokens of the dataset.
Runtimes with your example file: 200ms with filter, 260 ms without. Thanks to the filtering, a filtered list is even faster than the unfiltered.

Windows Batch script stops reading a file after a record has been written via IF in DO loop

Sometimes I think my relationship with the Windows command line is weighted in favour of Stockholms syndrome over anthing else. I'm hoping someone else in this world of punishing stuff has an answer for me!
Here's the background and the problem statement: I have a quite large script that does stuff with a for loop that steps through a file searching for a record number, and changing the record while writing the records around in a nice sequential batch way, ie records are written up to the target record; a changed record is written; the remaining records are written. I needed to add a new action verb to the existing set, which requires an additional IF clause. It suddenly stopped writing out remaining records after the found record had been changed. Couldn't find the answer.
So I started stripping away code until I reached this residual script. The IF clause in the FOR/ in / DO loop ... Leave it in, the script stalls after the written record as per the first sample below; leave it out, the FOR loop happily does it's thing, as per the second sample output. It gets stranger. Adding in script gives error messages, sometimes running through to completion, sometimes not ~ even a simple echo will give a parsing error. Placement in the script also seems to matter, which made debugging an absolute nightmare.
Clearly there is something that is triggering the command processor to quit the loop. SO I would pose the following two questions to the community:
What is causing the FOR /in /DO structure to stop processing records
What gives with the echo statements giving parsing errors? (echoing a variable name with a script line number, or just the number, for instance, is very low impact. )
Thanks. Code follows, any text file can be used as the second parameter, the first is a line number to action.
echo off
SETLOCAL enabledelayedexpansion
SET _filein=%~2
SET _line=%1
set _cnt=0
:: _filein = any file, _line = the line to be inspected, _cnt = loop counter
:: in the loop: _record = line value, _msg= display message if line is found
FOR /f "tokens=1 delims=" %%i IN ('type %_filein%') DO (
SET _record=%%i
SET /a _cnt+=1
IF [!_cnt!]==[%_line%] (
echo the line %_line% is !_record!
set _msg=the line is !_record! at position !_cnt!
goto sayrecord
)
echo not the line:
:sayrecord
echo !_cnt!- !_record!
)
:Xit
echo:
IF [%_msg%]==[] (
echo: left out
) ELSE (
echo: I'm in to see %_msg%
)
ENDLOCAL
exit /b
Test runs:
1. With the IF statement: (note parsing error statement)
H>_a 3 _files.txt
H>echo off
not the line:
1- notes.bat
not the line:
2- notesqa.bat
the line 3 is bulkfiledelete.bat
3- bulkfiledelete.bat
line was unexpected at this time.
H>
Without the IF:
H>_a 3 _files.txt
H>echo off
not the line:
1- notes.bat
not the line:
2- notesqa.bat
not the line:
3- bulkfiledelete.bat
not the line:
4- CheckAdminRights.bat
not the line:
: : :
not the line:
47- Reset connection 3 - renew.lnk
not the line:
48- ============
left out
H>
OK, so I have a code block that works thanks to #jwdonaahue for the initial clue; and #SomethingDark for the problem statement.
The :label is the problem here, although it works in many other production scripts it clearly is problematic. Instead of a script that drops to the bottom of the loop for processing, putting in an IF clause for each use case is what is needed.
#echo off
SETLOCAL enabledelayedexpansion
SET _filein=%~2
SET _line=%1
set _cnt=0
:: _filein = any file, _line = the line to be inspected, _cnt = loop counter
:: in the loop: _record = line value, _msg= display message if line is found
FOR /f "tokens=1 delims=" %%i IN ('type %_filein%') DO (
SET _record=%%i
SET /a _cnt+=1
IF [!_cnt!]==[%_line%] (
echo the line %_line% is !_record!
set "_msg=the line is !_record! at position !_cnt!"
echo not the line:
CALL :sayrecord
)
IF [!_cnt!] neq [%_line%] CALL :sayrecord
)
:Xit
echo:
IF [%_msg%]==[] (
echo: left out
) ELSE (
echo: I'm in to see %_msg%
)
ENDLOCAL
exit /b
:sayrecord
echo !_cnt!- !_record!
exit /b
i.e. to solve my problem,
add an IF clause for each action verb;
end with an `IF' clause which wraps the records that must be written unchanged
I'll also go through all the scripts and do a maint on them!
Given that your stated intent was to replace the content of %2 on line %1, you don't need delayed expansion or to set all of those variables:
#For /F "Tokens=1*Delims=]" %%I In ('Type "%~2"^|"%__AppDir__%find.exe" /V /N ""')Do #If "%%I"=="[%~1%" (Echo Inserted line content)Else Echo=%%J
#Pause
You would modify the content after Echo  and before ) to the replacement line content, and the last line is added just to ensure that you can read the output.
[Edit /]If you wanted to ask the end user for confirmation of the change before doing so, you could expand your code to incorporate that:
#For /F "Tokens=1*Delims=]" %%I In ('Type "%~2"^|"%__AppDir__%find.exe" /V /N ""')Do #If "%%I"=="[%~1" ("%__AppDir__%choice.exe" /M "Replace %%J with new content"&If ErrorLevel 2 (Echo=%%J)Else Echo Inserted line content)Else Echo=%%J
#Pause

concatenate string in for windows command

I want to concatenate to a string in a for command but in every iteration it doesn't update the str as I would want it to do.
the code is:
set x=0
for %G in (1,2,3) Do set x=%x%1
the value I would like x to get is: 0111.
the value accepted is: 01
I made a batch file to test this out and I got 0111 as you expected
here is the batch contents:
Setlocal EnableDelayedExpansion
set x=0
for %%G in (1,2,3) Do set x=!x!1
echo !x!
pause

Merge Two CSV Files by Column (Rather than Inserting New Lines)

I created two batch files:
1:
dir *.txt %t *.* /w/a/b/-p/o:gen | find "/">rezultate.csv
It gets the path and size and date and creation time of all text files from a directory and exports the result into a CSV file.
2:
#echo off
setlocal EnableDelayedExpansion
if exist results.csv del results.csv
for %%f in (D:\script\*.txt) do (
set i=0
for /F "tokens=2 delims=:" %%l in (%%f) do (
set /A i+=1
set line!i!=%%l
)
echo %%f, !line1!, !line2!,>> D:\script\results.csv
)
It gets the file path and what the file contains on the first 2 lines(also text files) from a specified directory and exports the result into a CSV file.
I attempted to combine the batch files and I managed to export the result from both batch files into the same CSV file but the output from the first batch file is exported on the first 5 lines and the output from the second batch file is exported on the next 5 lines.
I would like to merge the batch files so that the output can be exported from the first batch file wich will have one column and 5 lines and in the same CSV to export the output from the second batch file wich has 3 columns but not under the export of the first batch.I would like the CSV to have still 5 lines but 4 columns.
I also attempted to merge the CSV files with another batch file but I get the same result.
Please help with a solution if possible because I looked for solutions for more than one week...
Here's how I need the CSV file to look:
Final result will have to be like this:
Thanks for your help #dohaqatar7.
Here are the results that I reached today.
You were right about your asumption regarding the way I would like to merge the CSV files.
1:
I went for you're script for part 1 as it was more acurrate and I changed it a little bit and it will be like this:
#echo off
for %%a in (*.txt) do echo %%~ta,%%~za>>results.csv
Sample output
2:
I will remain with my script as it returns exactly what I want and it is accurate.
#echo off
setlocal EnableDelayedExpansion
for %%f in (D:\script\*.txt) do (
set i=0
for /F "tokens=2 delims=:" %%l in (%%f) do (
set /A i+=1
set line!i!=%%l
)
echo %%f, !line1!, !line2!,>>D:\script\results.csv
)
sample output
You have a sample also with the final result.
As for the script provided to merge the CSV files I was not able to make it work as it does not return the output in a new CSV file.Could you please change it a little bit so that I can use it.I hope I explained better right now.I would have given more details but I'm new around here and I'm limited by my reputation.
It would have been great if you could insert the path wich is "D:\scrip\filename\" but I can do that myself.
Kind regards,
Set Arg = WScript.Arguments
set WshShell = createObject("Wscript.Shell")
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
On Error Resume Next
Set Fso = CreateObject("Scripting.FileSystemObject")
Set File = Fso.OpenTextFile(Arg(1), 1, false)
If err.number <> 0 then
Outp.WriteLine "Error: " & err.number & " " & err.description & " from " & err.source
err.clear
wscript.exit
End If
Do Until Inp.AtEndOfStream And File.AtEndOfStream
Line = ""
Line2 = ""
Line=Inp.readline
Line2=File.readline
outp.writeline Line & "," & Line2
Loop
To use on screen
cscript //nologo <"path to script.vbs"> "" "c:\file1.txt" < "c:\file2.txt"
To put in a file
cscript //nologo <"path to script.vbs"> "" "c:\file1.txt" < "c:\file2.txt" > "file3.txt"
First off, I don't know that your first piece of code does what you say it does. When I run it, the file always remains empty. This code does what you claim the first pieces does.
#echo off
for %%a in (*.txt) do echo %%~ta,%%~za,%%~fa
If your code works for you, keep using it. If you start having issues with it, this code will work.
As for combining CSV files, I am a little uncertain about what you want. Here is what I assumed.
You want to take a.csv
a1,b1,c1
a2,b2,c2
and b.csv
d1
d2
and combine them into ab.csv
a1,b1,c1,d1
a2,b2,c2,d2
This code will take two arguments, the files to combine, and output the result to a new file.
#echo off
setlocal enabledelayedexpansion
set "line1=0"
for /f "tokens=*" %%a in (%1) do (
set "file1[!line1!]=%%a"
set /a line1+=1
)
set "line2=0"
for /f "tokens=*" %%a in (%2) do (
set "file2[!line2!]=%%a"
set /a line2+=1
)
if !line1! GTR !line2! (
set /a max=!line1!-1
) else (
set /a max=!line2!-1
)
set "mergedCSV=%~n1_%~n2.csv"
echo.>%mergedCSV%
for /l %%a in (0,1,%max%) do (
if "!file1[%%a]!"=="" (
echo !file2[%%a]! >> %mergedCSV%
) else (
if "!file2[%%a]!"=="" (
echo !file1[%%a]! >> %mergedCSV%
) else (
echo !file1[%%a]!,!file2[%%a]! >> %mergedCSV%
)
)
)

Resources