Advertisement

There's no such thing as a stupid question, but they're the easiest to answer.
Login
Search

Advertisement

DOS/Other DOS/Other
Search Search
Search for:
Tech Support Guy > > >

Append to end of line


(!)

Squashman's Avatar
Trusted Advisor with 19,645 posts.
THREAD STARTER
 
Join Date: Apr 2003
Location: 1265 Lombardi Ave
30-Apr-2008, 11:57 PM #1
Append to end of line
Batch files certainly aren't my strong suit. I can never figure out the linux bash equivalent in DOS.

I need to append some text to the end of every line in a file. In theory I guess I would like to just append the filename to the end of every line within the file. This is real easy with SED or AWK on Linux but can't seem to figure out the dos equivalent.
__________________
.
devil_himself's Avatar
Member with 4,910 posts.
 
Join Date: Apr 2007
Location: India
Experience: Advanced
01-May-2008, 12:40 AM #2
Greetings Squashman

Try This

Code:
@echo off
set addtext=hello!
if exist c:\tmpfile.txt del /q c:\tmpfile.txt
for /f "delims=" %%l in (c:\myfile.txt) Do (
      echo %%l %addtext% >> c:\tmpfile.txt
)
del /q c:\myfile.txt
ren c:\tmpfile.txt myfile.txt
TheOutcaste's Avatar
Computer Specs
Member with 9,028 posts.
 
Join Date: Aug 2007
Location: Oregon, USA
Experience: Intermediate
01-May-2008, 01:23 AM #3
Quote:
Originally Posted by devil_himself View Post
echo %%l %addtext% >> c:\tmpfile.txt
Note that the space between %%l and %addtext% will insert a space. If you don't want the space added, run them together:
echo %%l%addtext% >> c:\tmpfile.txt

i came up with something similar, allowing for filenames/paths with spaces:
Code:
@echo off
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:_t0 is the path to where the file you want to work on is
:located and _t1 is the file name. _t3 is the string you want to tack on
:You can always use command line parameters as well by using
:Set _t0=%1, Set _t1=%2, and Set _t3=%3
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Set _t0=c:\Test1
Set _t1=File1.txt
Set _t3=Add this string
PUSHD %_t0%
If EXIST tmp.txt del tmp.txt
For /F "usebackq delims=" %%A in ("%_t1%") do echo %%A%_t3% >>tmp.txt
del "%_t1%"
rename tmp.txt "%_t1%"
For %%A in (0 1 2) do Set _t%%A=
POPD
Problem is with both of these, any blank lines are removed from the file, so this:

Code:
Line1

Line3
becomes this

Code:
Line1 hello!
Line3 hello!
Instead of this
Code:
Line1 hello!
 hello!
Line3 hello!
Still trying to figure that part out, and/or a way to leave in the blank lines without adding anything, so the result will be this:
Code:
Line1 hello!

Line3 hello!
Also tried For /F "usebackq delims=" %%A in (`type "%_t1%"`) do... as the type command does send the blank lines to the screen, but the for statement ignores them.

I've got an idea though....

Jerry

Last edited by TheOutcaste; 01-May-2008 at 01:29 AM.. Reason: forgot the echo off command
devil_himself's Avatar
Member with 4,910 posts.
 
Join Date: Apr 2007
Location: India
Experience: Advanced
01-May-2008, 01:40 AM #4
I came up With This

Code:
@echo off
setlocal 
set addtext=hello!
for /f "delims=" %%a in (myfile.txt) do (echo/|set /p =%%a%addtext% & echo\ & echo\) >>new.txt
text file

Code:
Line1

Line3
output
Code:
Line1hello!  

Line3hello!
Edit :- Sorry It Adds A Blank Line if There's No Blank Line ...

Last edited by devil_himself; 01-May-2008 at 01:50 AM..
devil_himself's Avatar
Member with 4,910 posts.
 
Join Date: Apr 2007
Location: India
Experience: Advanced
01-May-2008, 01:59 AM #5
Ok ..This Should do it

Code:
:bof

    @echo off
    setlocal enabledelayedexpansion
    set addtext=hello!

:init

    for /f "delims=" %%a in ('findstr /n /v /c:"&$&$&$123" myfile.txt') do (
      set str=%%a
      set /a LineCount+=1
      set /a mod = LineCount/10 + 2
      call :PROCESS "!str!" !mod!
     )
  endlocal & goto :eof

  :PROCESS
  setlocal
  set str=%~1
  set offset=%2
  set str=!str:~%offset%!
  echo.!str! %addtext%
  endlocal & goto :eof

:eof
TheOutcaste's Avatar
Computer Specs
Member with 9,028 posts.
 
Join Date: Aug 2007
Location: Oregon, USA
Experience: Intermediate
01-May-2008, 05:55 AM #6
Ah, so many ways to do things. Neat approach to stripping the leading line numbers from the findstr command, devil_himself.

Here's what I've come up with. One for statement will add the string to every line, the other will leave blank lines blank. Using the 3rd parameter on the command line chooses to add the string to blank lines.

It the last line in the file does not have a carriage return at the end, this will add one. Feature of the echo command. I've got a batch file someplace that will strip that last carriage return, but can't find it at the moment.

Code:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Adds a text string onto the end of every line in a file
:Save code as a .bat or .cmd file, eg, addon.cmd
:usage: addon [drive:][path]filename string_to_add [flag]
:If filename or string_to_add contain spaces, they must be in quotes
:The flag parameter can be any character. If not specified, the string_to_add
:will not be added to blank lines.
:example: addon myfile.txt " Hello World" Y
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off
If [%1]==[] If [%2]==[] echo.Usage: & echo %0 [drive:][path]filename string_to_add [flag] &goto:eof
Set _t0=%~dp1
Set _t1=%~nx1
Set _t2=%2
Set _t2=%_t2:"=%
PUSHD %_t0%
copy file1.txt "file 1.txt"
If EXIST _f0.txt del _f0.txt
If [%3]==[] goto _noblank
For /F "usebackq skip=2 tokens=1* delims=]" %%A in (`find /v /n "" "%_t1%"`) do echo %%B%_t2%>>_f0.txt
goto _cleanup
:_noblank
For /F "usebackq skip=2 tokens=1* delims=]" %%A in (`find /v /n "" "%_t1%"`) do (if [%%B]==[] (echo.>>_f0.txt) Else echo.%%B%_t2%>>_f0.txt)
:_cleanup
del "%_t1%"
rename _f0.txt "%_t1%"
For /L %%A in (0,1,3) do Set _t%%A=
POPD
Jerry
Squashman's Avatar
Trusted Advisor with 19,645 posts.
THREAD STARTER
 
Join Date: Apr 2003
Location: 1265 Lombardi Ave
01-May-2008, 02:21 PM #7
You both are so gung ho I guess I will tell you what my ultimate plan is. I do alot of data processinng on a mainframe and we are sometime limited to what we can do with some of the software we have on the mainframe. So I sometimes like to preprocess the file before I put them on the mainframe to do our regular data processing.

Alot of the files we get sometimes don't have an identifying keycode on them to tell us what file is what. So I thought I could just append the filename to every record so I know what original input file the record came from. When I say record I mean a line of text. We refer to them as records because it is information about a person or company.

So on some jobs I get about 7 different files in that eventually have to be merged into one file after I have done a couple of different changes to it. But I would like to merge them all together on my PC before I put the file on the mainframe. But I will need to identify what lines(records) came from each file. So that is why I would need to append the filename to the end of each line. As it is parsing each file it will append the appropriate filename to the end of each line(record).

Here is one catch though. Each file has a header line at the beginning of each file. It identifies where each field starts within the line. I only need the header record once and it would be the first line in the output of the combined files.

I figured I could do a
set /P _Header=<somefile.txt

This would give me the first line of that file but I relly want the batch file to be generic enough that I will never have to enter in file names. I just want the batch file to parse all the files in the current directory. I just want to drop the batch file into the directory and execute it. So how would I do that without knowing the filenames and only out put the header record once from the first file it finds.

The other idea behind doing that command was to use it against the find command to kind of do a reverse find on the file. That way it would output all the records execept the header of every file.

find /V "%_Header%" somefile.txt >> combined_files.txt

So I now need to add the information I just talked about to your existing batch files you did for me.

If you guys want to know how easy it is to do this with sed....

sed -e "s/.$/filename.txt/g" filename.txt (This will add filename.txt to the end of ever line in a file.) I believe the .$ means find the CRLF(carriage return line feed). In unix it is just the dollar sign because they just use Line Feeds.

You can download native ports of alot of unix utilities from Sourceforge. You can use them in batch files just like any other dos command.
http://unxutils.sourceforge.net/

I find using these things alot more useful sometimes then trying to figure out how to do it in natively in dos.

Just an FYI, my files will never have a whole line full of spaces. Sometines the file come in with a End of File marker but that is about it. The end of file is usually just a line feed or a CRLF.
devil_himself's Avatar
Member with 4,910 posts.
 
Join Date: Apr 2007
Location: India
Experience: Advanced
01-May-2008, 09:11 PM #8
Quote:
Each file has a header line at the beginning of each file. It identifies where each field starts within the line. I only need the header record once and it would be the first line in the output of the combined files.
Sorry , I Don't Understand ... Can You Explain Giving An Example ...

Or Do You Mean To Say

Different Files May Have Different Header .. Just Extract The First Line From The First File Being Processed And Place It At The Top Of The Output File ...

Then Append The File Names To The End Of The Every Line ! And Merge All The Log Files ?
Squashman's Avatar
Trusted Advisor with 19,645 posts.
THREAD STARTER
 
Join Date: Apr 2003
Location: 1265 Lombardi Ave
01-May-2008, 09:47 PM #9
The header records are the same for all files. I just need the header record once. It should be the first record of the combined output.

Append the filename to the end of every record and merge all data files together.

First file will output the header record and all remaining records. Each line will have the filename it belongs to appended to the end of every line.

Name,Address,City,ST (This is the header record)
John Doe, 535 Brule Rd, San Jose, CA,filename1.txt
Jim Andersen, 512 Grand Ave, San Diego, CA,filename1.txt
Jane Smith, 423 Maple St, Seattle, WA,filename2.txt (This would be the second line of file 2. Skips the header record because I only need it once)
devil_himself's Avatar
Member with 4,910 posts.
 
Join Date: Apr 2007
Location: India
Experience: Advanced
02-May-2008, 12:44 AM #10
Try This

Code:
@echo off
setlocal enabledelayedexpansion
set tp=c:\tp.txt
if exist c:\tmpfile.txt del /q c:\tmpfile.txt
(for /f "tokens=*" %%a in ('dir /b /a-d *.txt') do (
   (for /f "tokens=*" %%i in ('cmd /c for /f "tokens=*" %%j in (%%a^) do echo %%j ^^^& exit') do set f=%%i)
     (for /f "skip=1 usebackq delims=" %%b in ("%%~dpnxa") do (
     echo %%b,%%~nxa >> "%tp%"
  ))
))

echo %f% >c:\tmpfile.txt
type "%tp%" >>c:\tmpfile.txt
del /q "%tp%"
Squashman's Avatar
Trusted Advisor with 19,645 posts.
THREAD STARTER
 
Join Date: Apr 2003
Location: 1265 Lombardi Ave
03-May-2008, 08:50 PM #11
I tried running it last night before I left from work but I got an erro that said tp.txt does not exist.

But I was able to figure it out with some of the existing Unix Utilites that have been ported to Windows.

Code:
:: delete any existing header.txt file
if exist header.txt del /q header.txt

:: delete any existing combined_output.dat files
if exist combined_ouput.dat del /q combined_output.dat

:: create header record to reverse match against all files and output as first record to combined_output file
:: All Input files must end in the file extension CHR
head -q -n1 *.CHR | head -n1 > header.txt

:: Add Filename Field to end of header line
:: Also Adds the delimiter and surround characters around the Field name
cat header.txt | sed -e "s/.$/:\"Filename\"/g" > combined_output.dat

:: Append the Filename to the end of each line of every file and combine all files together
:: Also adds the delimter and surround character around the variable
:: All Input Files must end in the File extension CHR
:: FOR /F "tokens=*" %%A IN ('dir /b /a-d *.CHR') DO cat %%A | grep -v -f header.txt | sed -e "s/.$/:\"%%A\"/g" >> combined_output.dat
FOR /F "tokens=*" %%A IN ('dir /b /a-d *.CHR') DO cat %%A | grep -v -f header.txt | sed "s/.$/\":\"%%A\""/" >> combined_output.dat


:: Clean UP
del /q header.txt
Had one heck of a time with the second SED statement that appends the filename to end of every line. For some reason I had to escape the quotes a couple of times. I didn't need to do it on the header record but for some reason it made me do it on the other lines. I kept the original statement in there for reference, I still don't understand why it doesn't work.
devil_himself's Avatar
Member with 4,910 posts.
 
Join Date: Apr 2007
Location: India
Experience: Advanced
03-May-2008, 09:37 PM #12
So Are You Planning To Use The "Unix Utilities" Or Batch File

I tested the batch its running fine ... Try Running It with "Echo On" and Two Lines In Two Text File then Copy And Paste The Output From The Command Window .
TheOutcaste's Avatar
Computer Specs
Member with 9,028 posts.
 
Join Date: Aug 2007
Location: Oregon, USA
Experience: Intermediate
03-May-2008, 10:02 PM #13
devil_himself's file seems to work fine for me as well. One comment, it does tack on a space after the filename; If that's a problem, just need to remove the space in this line:
echo %%b,%%~nxa >> "%tp%"
so it looks like this:
echo %%b,%%~nxa>> "%tp%"

Here's what I came up with:

Code:
@Echo off
::Set Output file name here
Set _f{1}=Combined.txt
If EXIST "%_f{1}%" Del "%_f{1}%"
::Gets first filename in alphabetical order, excluding the batch file
For /F "tokens=*" %%A In ('dir /b /a-d /o:-n ^|Find /I /V "%~nx0"') Do Set _t0=%%A
::Read Header from first line in first file
For /F "usebackq tokens=*" %%A In (`Find /V /N "" "%_t0%" ^|Findstr /B /C:"[1]"`) Do Set _t1=%%A
::Output Header to temp file
>%temp%\_f{0} Echo.%_t1:~3%
::Read lines from each file excluding the batch file and excluding the header line
::Output to temp file adding ,filename to end of line
For /F "tokens=*" %%A In ('dir /b /a-d /o:n ^|Find /I /V "%~nx0"') Do (
For /F "usebackq skip=2 tokens=1* delims=]" %%B In (`Find /V /N "" "%%A" ^|Find /I /V "%_t1%"`) Do @Echo %%C,%%A>>%temp%\_f{0}
)
Move %temp%\_f{0} "%_f{1}%"
For /L %%A In (0,1,1) Do Set _t%%A=
Jerry
Squashman's Avatar
Trusted Advisor with 19,645 posts.
THREAD STARTER
 
Join Date: Apr 2003
Location: 1265 Lombardi Ave
04-May-2008, 12:48 AM #14
I am using those Unix Utilites in a batch file. They are quite powerful as you can see from the small amount of code I had to write vs the the nice batch files you guys wrote. I guess I would like to use what you guys wrote. I have a hard time getting anyone to change at work. I will try testing it again when I get back to work. But all I can tell you is that it said it could not find that text file. I think it is because all my data files end in the file extension .CHR. Would that wreak havoc with the stuff you guys wrote. I would assume so. I was trying to figure out a way to write mine without having to know the file extension of the data files but couldn't figure it out.

I probably should mention that the filename needs to be delimted and the header record needs the word Filename appended to the end as well. The header record and the data are colon delimited and have quotes surrounding the data.

The header record and data come in like this.

"Name":"Address":"City":"State":"ZipCode"
"John Doe":"503 Grand Ave":"San Jose":"CA":"93456"

Need it to look like this:
"Name":"Address":"City":"State":"ZipCode":"Filename"
"John Doe":"503 Grand Ave":"San Jose":"CA":"93456":"File1.txt"
TheOutcaste's Avatar
Computer Specs
Member with 9,028 posts.
 
Join Date: Aug 2007
Location: Oregon, USA
Experience: Intermediate
04-May-2008, 01:43 AM #15
My script doesn't care about the extension, devil's looks for *.txt -- changing that to *.chr in the For statement would fix that. Don't know how his would work with quoted data, or adding a comma, but shouldn't take much of a change.

Tweaked mine to work with quoted data strings and using the colon, and this should work. Be sure to change the output file name (part in red) to use the extension you want:

Code:
@Echo off
::Set Output file name here
Set _f{1}=Combined.txt
If EXIST "%_f{1}%" Del "%_f{1}%"
::Gets first filename in alphabetical order, excluding the batch file
For /F "tokens=*" %%A In ('dir /b /a-d /o:-n ^|Find /I /V "%~nx0"') Do Set _t0=%%A
::Read Header from first line in first file
For /F "usebackq tokens=*" %%A In (`Find /V /N "" "%_t0%" ^|Findstr /B /C:"[1]"`) Do Set _t1=%%A
::Output Header to temp file
>%temp%\_f{0} Echo.%_t1:~3%:"Filename"
::Read lines from each file excluding the batch file and excluding the header line
::Output to temp file adding :"filename" to end of line
For /F "tokens=*" %%A In ('dir /b /a-d /o:n ^|Find /I /V "%~nx0"') Do (
For /F "usebackq skip=2 tokens=1* delims=]" %%B In (`Find /V /N "" "%%A" ^|Findstr /I /V /B /C:"[1"`) Do @Echo %%C:"%%A">>%temp%\_f{0}
)
Move %temp%\_f{0} "%_f{1}%"
For /L %%A In (0,1,1) Do Set _t%%A=
HTH

Jerry

Last edited by TheOutcaste; 04-May-2008 at 03:15 AM.. Reason: Correcting Comment line in Code
As Seen On

BBC, Reader's Digest, PC Magazine, Today Show, Money Magazine
WELCOME TO TECH SUPPORT GUY!

Are you looking for the solution to your computer problem? Join our site today to ask your question. This site is completely free -- paid for by advertisers and donations.

If you're not already familiar with forums, watch our Welcome Guide to get started.


(clock)
THIS THREAD HAS EXPIRED.
Are you having the same problem? We have volunteers ready to answer your question, but first you'll have to join for free. Need help getting started? Check out our Welcome Guide.

Search Tech Support Guy

Find the solution to your
computer problem!




Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools


WELCOME
You Are Using: Server ID
Trusted Website Back to the Top ↑