Batch: convert pipe delimited text file to comma delimited csv file - batch-file

I have a .txt file like this:
Customer Number||Customer Name||Partner Number||Partner Name||Customer Country
1ABC||Jame||1234||Anny||USA
2DEF||Susan||5678||Prissy||UK
My output should be a .csv file with no empty columns.
This is what I tried:
#echo off
setlocal disableDelayedExpansion
set input="C:\a.txt"
set output="C:\Customer_Pipe.csv"
>%output% (
for /f "tokens=*" %%a in ('input"') do (
set line=%%a
setlocal enableDelayedExpansion
echo "!line:|=","!">>"%~2"
)
)

If you want to read the file stored in variable INPUT, you need to read it as %INPUT% to do that (you stated INPUT literally, with odd quotation). When you specify '' within the set of for /F, the part within () is interpreted as a command rather than a file, so for /F tries to execute command input which cannot be found and so the script fails. I stringly recommend to put "" around the specified file, together with the usebackq option, in order to avoid trouble with white-spaces in paths/file names.
If you want to write into the file stored in variable OUTPUT, you must not redirect the echo to somewhere else (you placed >>"%~2" in the code).
Here is the code as I would write it:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define constants here:
set "INPUT=%~1"
set "OUTPUT=%~2"
if not defined INPUT exit /B 1
if not defined OUTPUT set "OUTPUT=con"
> "%OUTPUT%" (
for /F usebackq^ delims^=^ eol^= %%L in ("%INPUT%") do (
set "LINE=%%L"
setlocal EnableDelayedExpansion
echo(!LINE:^|^|=,!
endlocal
)
)
endlocal
exit /B
The input file for the batch program must be provided as the first command line argument. The second argument (optional) is the output file.
Note that this script does not check whether the input data contains , characters, which impact the way the converted file is treated. If you want to put quotation marks around all fields of the returned CSV data to avoid data interpretation troubles, replace the above echo command line by:
echo("!LINE:||=","!"
The output data (with the original echo command line) looks like this:
Customer Number,Customer Name,Partner Number,Partner Name,Customer Country
1ABC,Jame,1234,Anny,USA
2DEF,Susan,5678,Prissy,UK
The output data with the modified echo command line looks like this:
"Customer Number","Customer Name","Partner Number","Partner Name","Customer Country"
"1ABC","Jame","1234","Anny","USA"
"2DEF","Susan","5678","Prissy","UK"

There are two problems in your code.
1)
You use setlocal EnableDelayedExpansion, that's a good idea, but you have to close it with endlocal else you get an error after ~32 setlocals.
2)
Your replace functions looks a bit odd.
You add some quotes, they will be part of the output later.
You could try this.
echo(!line:^|^|=,!
At all
>%output% (
for /f "tokens=*" %%a in (%input%) do (
set "line=%%a"
setlocal EnableDelayedExpansion
set "line=!line:||=,!"
(echo(!line!)
endlocal
)
)

Related

Combine lines in text file using batch

I want to make a program that takes the content of the second line of a text file and puts it on the first. (It doesn't matter if the second doesn't get edited)
for /f "tokens=1" %%t in (file.txt) do set string1=%%t
for /f "tokens=2" %%t in (file.txt) do set string2=%%t
echo %string1%%string2%>file.txt
I have two issues hat I can't seem to be able to fix.
One: the loops only include the first word of each line in the variables.
Two: Echo doesn't replace the first line of the file with the variables given and instead writes ECHO command deactivated (I have the French version of Windows 10 and simply translated what got written in the file, the text in English Windows version might be slightly different, but you get the idea)
If you have any suggestions, I would appreciate if you explain what the code you provide does (I always like to learn)
Your question is not clear and can be understood in several different ways. Anyway, this management is simpler with no for command:
#echo off
setlocal EnableDelayedExpansion
< file.txt (
rem Takes the content of the first line
set /P "line1="
rem Takes the content of the second line and puts it on the first
set /P "line2="
echo !line1!!line2!
rem It doesn't matter if the second line doesn't get edited
echo !line2!
rem Copy the rest of lines
findstr "^"
) > output.txt
move /Y output.txt file.txt
The FOR command uses a space as a delimiter by default. So you have to tell it to not use any delimiters with the DELIMS option. Also, you should be able to do this with a single FOR /F command. Just hold the previous line in a variable.
#ECHO OFF
setlocal enabledelayedexpansion
set "line1="
(for /f "delims=" %%G in (file.txt) do (
IF NOT DEFINED line1 (
set "line1=%%G"
) else (
echo !line1!%%G
set "line1="
)
)
REM If there are an odd amount of lines, line1 will still be defined.
IF DEFINED line1 echo !line1!
)>File2.txt
EDIT: I think I completely misunderstood your question. Once you clarify your question I will repost a code solution if needed.
Use skip to omit the first line and write the 2nd line twice. In general an edit of a file implies a rewrite to a new file and possibly a rename to retain the old file name.
:: Q:\Test\2018\07\25\SO_51508268.cmd
#Echo off
Set "flag="
( for /f "usebackq skip=1 delims=" %%A in ("file1.txt") Do (
If not defined flag (
Echo=%%A
Set flag=true
)
Echo=%%A
)
) >file2.txt
Del file1.txt
Ren file2.txt file1.txt
After running the batch a file1.txt with initially numbered lines 1..5 looks like this:
> type file1.txt
2
2
3
4
5

Nested /F looping and If statements in batch file

I have two .txt files. One contains numbers, and the other one contains filepaths. I want to combine these two files to a .csv. The combination is based on wether the number (from nrs.txt) is in the string of the filepath (nodups.txt).
Now I have the following code for this:
#setlocal enableextensions enabledelayedexpansion
for /F %a IN (Output\nrs.txt) DO (
SET "nrs=%a"
for /F %b IN (Output\nodups.txt) DO (
SET "pathstring=%b"
SET csvdelim=,
IF NOT x!pathstring:%nrs%=""!==x%pathstring% %nrs%,%pathstring%>>new2017.txt
)
)
#endlocal
However, I keep having the following issues with the code:
The pathstring never seems to get set. (when I run the code without the if statement, The nrs variable gets set but the pathstring is set to %b). I've seen a lot of possible solutions on here already but none seem to work for me (setting variables like !var! and using usebackq).
The IF statement in the second for loop gets the following error message =""!==x%pathstring% was unexpected at this time. The ="" should remove the nr. from the path (if its there). When I replace "" with something else it still does not work.
The file contents are:
File nrs.txt:
12345
12245
16532
nodubs.txt:
C:\tmp\PDF_16532_20170405.pdf
C:\tmp\PDF_1234AB_20170405.pdf
C:\tmp\PDF_12345_20170506.pdf
Desired output:
12345, C:\tmp\PDF_12345_20170506.pdf
16532, C:\tmp\PDF_16532_20170405.pdf
I really hope someone can help me out with this !
This solution use a different approach, based on arrays:
#echo off
setlocal EnableDelayedExpansion
rem Load array from nodubs.txt file
pushd "Output"
for /F "tokens=1,2* delims=_" %%a in (nodubs.txt) do set "nodubs[%%b]=%%a_%%b_%%c"
rem Process nrs.txt file and show output
(for /F %%a in (nrs.txt) do (
if defined nodubs[%%a] echo %%a, !nodubs[%%a]!
)) > new2017.txt
In a batch file for variables need two percent signs.
There is no need to put %%A into a variable, use it directly.
#setlocal enableextensions enabledelayedexpansion
for /F %%a IN (Output\nrs.txt) DO (
findstr /i "_%%a_" Output\nodups.txt >NUL 2>&1 || >>new2017.txt Echo %%a
)
#endlocal
Instead of a second for, I'd use findstr to search for the entry of nrs.txt enclosed in underscores.
if no find use condiotonal execution on failure || to write to the new file.
According to changed preliminaries another answer.
#Echo on
Pushd Output
for /F "tokens=1-3 delims=_" %%A IN (
' findstr /G:nrs.txt nodubs.txt'
) DO >>"..\new2017.txt" Echo %%B, %%A_%%B_%%C
Popd
sample output:
> type ..\new2017.txt
16532, C:\tmp\PDF_16532_20170405.pdf
12345, C:\tmp\PDF_12345_20170506.pdf

Splitting CSV files on specific text

I have got a system that generates CSV files containing time based data.
Some files have data from two different dates. I want to break up these files into two files, one containing the data from the first day, the other containing the data from the next day. The original file looks like this:
09.01.2015 00:00:00,0385 - Veerhaven,VP01 in bedrijf hoog toerental,K,Process message.
09.01.2015 00:00:00,0385 - Veerhaven,VP01 in bedrijf laag toerental,G,Process message.
08.01.2015 23:59:55,1475 - Schaatsbaan,PO01 in bedrijf,G,Process message.
08.01.2015 23:59:52,0311 - Abraham van Stolkweg,PO01 in bedrijf,G,Process message.
The first 10 Characters are the date of the event. I want to break up the file in two output files seperating the data from the two days. I have to do this using batch processing because it has to be done every day over a lot of files.
I hope someone can help me on my way. Thanks in advance.
#echo off
setlocal enableextensions disabledelayedexpansion
set "file=c:\somewhere\data.txt"
for %%f in ("%file%") do for /f "usebackq" %%a in ("%%~ff") do (
if not defined %%a (
findstr /b /c:"%%a" "%%~ff" > "%%~dpnf.%%a%%~xf"
set "%%a=1"
)
)
The first for command is used only to retrieve a reference to the file and being able to separate path, filename and extension (that will be used later to generate the output files).
Second for loop reads the input file and for each line retrieves the first token/field in the line using spaces as delimiters (the default behaviour in for /f command). This value is used to filter the input file and declare environment variables:
If the variable is not defined, it is the first time the value is seen, matching records are extracted from the input file to a new output file and the variable is defined.
If the variable is defined, this value has been seen and the corresponding output file generated, the extraction is skipped and the process continues reading the next line.
edited to adapt to comments
#echo off
setlocal enableextensions disabledelayedexpansion
set "files=c:\somewhere\*.txt"
set "outputFolder=c:\where\to\put\files"
for %%f in ("%files%") do (
setlocal
for /f "usebackq" %%a in ("%%~ff") do if not defined %%a (
findstr /b /c:"%%a" "%%~ff" > "%outputFolder%\%%~nf.%%a%%~xf"
set "%%a=1"
)
endlocal
)
The wildcard management in the input needs no changes: for %%f iterates over the indicated set, being it only a file or a set of files.
The output folder is stored in a environment variable. The redirection is changed to use the variable insted of the path of the input file.
As the variables used to determine if the indicated token has been processed needs to be deleted for each file processed, the loop that processes the file contents is wrapped in a pair of setlocal/endlocal that cleans the flag variables after each file has been processed
read HELP FOR to learn how to use the FOR command to loop over the lines of a file and parse its contents. Then, try
for /f "tokens=1,*" %%a in (timedata.txt) do (
echo %%a ... %%b
)
you see that you may use %%a to split the files by date, so you could figure out something like
for /f "tokens=1,*" %%a in (timedata.txt) do (
echo %%b >>timedata.%%a.txt
)
or more generically
set fn=%~dpn1
set fx=%~x1
for /f "tokens=1,*" %%a in (%~1) do (
echo %%b >>%fn%.%%a%fx%
)

Batch file to create multiple variables from single lines in a text file

I have a text file with the names of computer names and corresponding static i.p. addresses in the following format.
COMPUTER NAME:PC ADDRESS=154.100.1.1 MASK=255.255.254.0
COMPUTER NAME:PC2 ADDRESS=100.100.1.1 MASK=255.255.254.0
I would like to take the values from each line and put them as variables in a batch file for use later. Is this possible? The overall goal is to have the values from this easily edited text file to be used in netsh commands in another batch file.
I've looked around and found ways to take lines of a text file and place them in one variable using the snippet below. However, I do not know how to create multiple variables from one line. If someone could help me with this I'd greatly appreciate it!
#echo o
setlocal enabledelayedexpansion
set Counter=1
for /f %%x in (D:\COMP_T.txt) do (
set "comp!Counter!=%%x"
set /a Counter+=1
)
This should work:
#echo off
setlocal EnableDelayedExpansion
set "Count=1"
for /f "tokens=1,2,3,4,5,6,7 delims==: " %%A in (C:\File.txt) do (
set "%%A[!Count!]=%%C"
set "%%D[!Count!]=%%E"
set "%%F[!Count!]=%%G"
set /a "Count+=1"
)
:: Call other batch script here.
endlocal
Example Output:
COMPUTER[1]=PC
COMPUTER[2]=PC2
ADDRESS[1]=154.100.1.1
ADDRESS[2]=100.100.1.1
MASK[1]=255.255.254.0
MASK[2]=255.255.254.0
Here is a solution that avoids the need for delayed expansion. It uses FINDSTR to insert a line number followed by : at the beginning of each line. The search string of "^" is guaranteed to match every line in the file.
The only other issue is to set TOKENS and DELIMS to parse the line properly.
#echo off
setlocal
for /f "tokens=1,4,6,8 delims=:= " %%A in ('findstr /n "^" "d:\comp_t.txt"') do (
set "comp%%A=%%B"
set "addr%%A=%%C"
set "mask%%A=%%D"
set "counter=%%A"
)
To use the set of variables in another batch file, line by line, just parse the lines as done in other answers here, and call the other batch file with the metavariables.
#echo off
for /f "tokens=1,2,3,4,5,6,7 delims==: " %%a in ('type "File.txt" ') do (
echo "computer_name=%%c"
echo "address=%%e"
echo "mask=%%g"
Call "batch script" "%%c" "%%e" "%%g"
)

How to change an image tag url in multiple html files using batch script?

There are more than 10 html files with image tags. Every time we deploy our build onto test site we need to change the img source. for eg <img src=/live/Content/xyz.png />
to <img src=/test/Content/xyz.png />.
After looking around and reading for sometime, i have come up with the following batch script, however i cant figure out how do i go further from here :
for /r %%i in (*.html) do echo %%i
for %%f in (*.html) do (
FOR /F %%L IN (%%f) DO (
SET "line=%%L"
SETLOCAL ENABLEDELAYEDEXPANSION
SET "x= <--------------------WHAT DO I SET HERE?
echo %x%
ENDLOCAL )) pause
This is my first batch script, could anyone please guide me in the right direction?
#ECHO OFF
SETLOCAL enabledelayedexpansion
for /r U:\ %%i in (*.html) do (
echo found %%i
SET outfile="%%~dpni.lmth"
(
SETLOCAL disabledelayedexpansion
FOR /F "usebackq delims=" %%L IN ("%%i") DO (
SET "line=%%L"
SETLOCAL ENABLEDELAYEDEXPANSION
SET "line=!line:/live/=/test/!
echo !line!
ENDLOCAL
)
ENDLOCAL
)>!outfile!
)
pause
GOTO :EOF
How about this development?
Notes:
I've modified your FOR/R to ECHO the HTML file being processed and use %%i rather than switching to %%f. U: is my RAMDRIVE; you'd need to modify that to suit.
outfile is set to generate a filename which matches the HTML filename, but with a .lmth extension (can't update in-place) - it gets that from the ~dpn prefixing the i, which means the drive, path and name of the file %%i. It's quoted to take care of potential spaces in the filename or pathname.
The next logical statement is (for /f...[lines] )>!outfile! which sends any echoed text to a NEW file !outfile!. The enabledelayedexpansion in the second physical line of the batch makes !outfile! the RUN-TIME value - as it is changed within the FOR r outer loop.
Since the actual HTML filename in %%i may contain spaces, it needs to be quoted, hence the 'usebackq' clause in the FOR/F. The delims= clause ensures that the ENTIRE line from the file "%%i" is applied to %%L - not just the first token (well, actually, makes the entire line the first token).
The SET command substitutes the string "/test/" for any occurrence of "/live/" in the RUN-TIME value of the variable lineand assigns the result to line. The resultant value is then ECHOd - which is redirected to outfile
Note that in your original, you would be assigning x in the set x= but echo %x% would have reproduced x as it stood when the line was PARSED because batch substitutes the value of any variable for %var% as part of the parsing phase. Consequently, the line would have become simply ECHO (since x would likely be unassigned) and bizarrely would have reported the echo state (Echo is OFF)
A couple of gatchas here. First, % and some other characters are notoriously hard to process with batch, so be careful. Next, FOR/F will bypass empty lines. This can be overcome if required. Third, this will replace ANY occurrence of /live/ in any case with /test/
Good luck!
Edit to support exclamation marks: 20130711T0624Z
Added SETLOCAL enabledelayedexpansion line and ENDLOCAL just before )>!outfile! to match

Resources