1. Computer problem? Tech Support Guy is completely free -- paid for by advertisers and donations. Click here to join today! If you're new to Tech Support Guy, we highly recommend that you visit our Guide for New Members.

Append to end of line

Discussion in 'DOS/Other' started by Squashman, Apr 30, 2008.

Thread Status:
Not open for further replies.
Advertisement
  1. Squashman

    Squashman Trusted Advisor Thread Starter

    Joined:
    Apr 4, 2003
    Messages:
    19,731
    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.
     
  2. devil_himself

    devil_himself

    Joined:
    Apr 7, 2007
    Messages:
    4,910
    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
    
     
  3. TheOutcaste

    TheOutcaste

    Joined:
    Aug 7, 2007
    Messages:
    9,028
    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
     
  4. devil_himself

    devil_himself

    Joined:
    Apr 7, 2007
    Messages:
    4,910
    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 ... :eek: :mad:
     
  5. devil_himself

    devil_himself

    Joined:
    Apr 7, 2007
    Messages:
    4,910
    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
     
  6. TheOutcaste

    TheOutcaste

    Joined:
    Aug 7, 2007
    Messages:
    9,028
    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
     
  7. Squashman

    Squashman Trusted Advisor Thread Starter

    Joined:
    Apr 4, 2003
    Messages:
    19,731
    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.
     
  8. devil_himself

    devil_himself

    Joined:
    Apr 7, 2007
    Messages:
    4,910
    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 ?
     
  9. Squashman

    Squashman Trusted Advisor Thread Starter

    Joined:
    Apr 4, 2003
    Messages:
    19,731
    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)
     
  10. devil_himself

    devil_himself

    Joined:
    Apr 7, 2007
    Messages:
    4,910
    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%"
    
     
  11. Squashman

    Squashman Trusted Advisor Thread Starter

    Joined:
    Apr 4, 2003
    Messages:
    19,731
    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.
     
  12. devil_himself

    devil_himself

    Joined:
    Apr 7, 2007
    Messages:
    4,910
    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 .
     
  13. TheOutcaste

    TheOutcaste

    Joined:
    Aug 7, 2007
    Messages:
    9,028
    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
     
  14. Squashman

    Squashman Trusted Advisor Thread Starter

    Joined:
    Apr 4, 2003
    Messages:
    19,731
    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"
     
  15. TheOutcaste

    TheOutcaste

    Joined:
    Aug 7, 2007
    Messages:
    9,028
    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}=[COLOR="Red"]Combined.txt[/COLOR]
    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
     
  16. Sponsor

As Seen On
As Seen On...

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.

Join over 733,556 other people just like you!

Loading...
Thread Status:
Not open for further replies.

Short URL to this thread: https://techguy.org/708872