Windows Command batch script to add filename to end of each row in a merged text file

19,289

Solution 1

There is a simple two liner that works from the command line if you are willing to prefix each line with the file name instead of putting the file name at the end. This solution is extremely fast.

cd "C:\My Documents\Data"
findstr "^" *.txt >output.log

Each line will have the format of filename:line content

It is important that your output file use a different extension than the files you are merging. Otherwise you run the risk of the command processing its own output!

The other option is to make sure the output goes to a different folder, perhaps the parent folder:

cd "C:\My Documents\Data"
findstr "^" *.txt >..\output.txt

Or, if you are willing to include the full path to each file in your output, then make sure current directory is not the same as your source, and use

findstr "^" "C:\My Documents\Data\*.txt" >output.txt

The only drawback to the above solution is that problems can arise if the last line of a text file does not end with a newline character. This will cause the first line of the next file to be appended to the last line of the prior file. Something like: FILENAME1:last line without newlineFILENAME2:first line of next file

A simple script can append a newline to files that are missing the newline on the last line. Then the files can be safely merged with the filename prefix on each line:

@echo off
if "%~1" equ ":FindFiles" goto :FindFiles

cd "C:\My Documents\Data"

:: Append newline to text files that are missing newline on last line
for /f "eol=: delims=" %%F in ('"%~f0" :FindFiles') do echo(>>"%%F"

:: Merge the text files and prefix each line with file name
findstr "^" *.txt >output.log

exit /b


:FindFiles
setlocal enableDelayedExpansion

:: Define LF to contain a newline character
set lf=^


:: The above 2 blank lines are critical - do not remove

:: List files that are missing newline on last line
findstr /vm "!lf!" *.txt

Solution 2

You'll need to add each line in the file individually:

@ECHO OFF
ECHO Creating %1...
SET "sourcedir=c:\sourcedir"
FOR /F "delims=" %%G IN ('DIR /B /a-d "%sourcedir%\*.txt"') DO (
ECHO Adding %%G
ECHO. >> Output.txt
for /f "usebackq tokens=*" %%a in ("%sourcedir%\%%~G") do (
Echo %%a - %%G >> Output.txt 
)
) 

Note in the second last line, the file name and the line is seperated by a -, you can replace this with whatever (don't forget to check for escaping characters) or can get rid of this if you want.

I'm sure that will work, but if it doesn't, tell me the Error message and I can fix it for you.

Mona

---- [edit:pw]
Close - major problem was the ( on the FOR ... %%G line was on the line following the DO - must be on the same line as the DO.

  • Added /a-d to the DIR to prevent subdirectory names matching
  • changed "usebackq tokens=1" to use conventional quotes and allow spaces in filenames
  • assigned target directory name to sourcedir variable and included %sourcedir% in both FOR statements to allow execution from anywhere, otherwise the filenames found in C:\My Doc.... would be searched-for in the current directory for replication into the output.

  • OP needs to change value assigned to sourcedir to C:\My Documents\Data

Share:
19,289
Admin
Author by

Admin

Updated on June 25, 2022

Comments

  • Admin
    Admin almost 2 years

    I a new to windows command line scripts. I have a batch file which i use to merge multiple text files into one. However i want to be able to also add the name of the text file the row comes from to the end of each row in the merged file.

    This is the script i am currently working with:

    @ECHO OFF
    ECHO Creating %1...
    FOR /F "usebackq tokens=1" %%G IN (`DIR /B "C:\My Documents\Data\*.txt"`) DO         
    (
    ECHO Adding %%G
    ECHO. >> Output.txt
    TYPE %%G >> Output.txt 
    ) 
    

    Now i know that to get the filename into the output file i need to use:

    ECHO %%G >> Output.txt 
    

    However i'm not sure how i would add this to the current script so it adds the filename to each row and I have had no luck with finding any examples.