Link to home
Start Free TrialLog in
Avatar of Rexx
RexxFlag for United States of America

asked on

Combine multiple .csv into one with file name

The following batch code combines multiple .csv files into one. What additional code would be needed to include the file name.

@echo off
setlocal
set FileMask=C:\Temp\test*.csv
set OutFile=C:\Temp\test_combined.csv
for %%a in ("%FileMask%") do (
	for /f "delims=" %%h in ('type "%%a"') do (
		>"%OutFile%" echo %%h
		goto :Combine
	)
)
:Combine
for %%a in ("%FileMask%") do (
	echo Processing %%a ...
	if /i "%%a"=="%OutFile%" (
		echo ... skipped result file.
	) else (
		more +1 "%%a" >>"%OutFile%"
	)
)
echo Done.

Open in new window

Avatar of Bill Prew
Bill Prew

Try this one line addition:

@echo off
setlocal
set FileMask=C:\Temp\test*.csv
set OutFile=C:\Temp\test_combined.csv
for %%a in ("%FileMask%") do (
	for /f "delims=" %%h in ('type "%%a"') do (
		>"%OutFile%" echo %%h
		goto :Combine
	)
)
:Combine
for %%a in ("%FileMask%") do (
	echo Processing %%a ...
	if /i "%%a"=="%OutFile%" (
		echo ... skipped result file.
	) else (
		echo %%a>>"%OutFile%"
		more +1 "%%a" >>"%OutFile%"
	)
)
echo Done.

Open in new window

~bp
Avatar of Rexx

ASKER

Rather it be in its own column so that the file name is listed with each record from the file:
Combined.tif
Is the header line the same in all files, and what does it look like?  I think we can use that to take a slightly different approach to get the results you want.

~bp
Avatar of Rexx

ASKER

Yes the header line is the same in all files. The initial script I started with (at the top) just includes the header of the first file. So I'm wanting to add another column to that named "File Name".

Here is code that works the way I want it to but for some records (in the combined file) it has issues keeping the entire field of a column together.

@echo off
setlocal EnableDelayedExpansion
set FileMask=C:\1_test\*.csv
set OutFile=C:\0_test\combined.csv
set Header=
(for %%F in ("%FileMask%") do (
  if not defined header set /P header=<%%F& echo File_Name,	!header!
  for /F "skip=1 usebackq delims=" %%L in ("%%~F") do echo %%~F,	%%L
))>"%OutFile%"

Open in new window

This is pretty close, but not perfect.  It does what we want, but the only wrinkle is the filename has a colon after it on each line, rather than a comma.  Depending on what you do with the file though, maybe that works?

@echo off
setlocal

set BaseDir=B:\EE\EE28942070\Files
set FileMask=test*.csv
set OutFile=B:\EE\EE28942070\Output\test_combined.csv

pushd "%BaseDir%"
call :GetHeader
call :GetData
popd

echo Done.
exit /b


:GetHeader
  for %%F in ("%FileMask%") do (
  	for /f "delims=" %%H in ('type "%%~F"') do (
      set Header=%%H
      echo.Filename,%%H>"%OutFile%"
      exit /b
  	)
  )
  exit /b

:GetData
  findstr /v /l /c:"%Header%" "%FileMask%">>"%OutFile%"
  exit /b

Open in new window

~bp
Avatar of Rexx

ASKER

Unfortunately that won't work because the data in some columns will either get carried over into another column or get added as another "partial" record.

When I do a more +1 this issue goes away.

The following code provides a header and combines the data correctly every time. It even includes a field in the header for "File_Name" (last field of header).

Is there away to get the File_Name included during the combine?
(It doesn't matter whether the File_Name is in the first column or the last column. if it can be added to each record without changing anything else we're done.)

@echo off
setlocal EnableDelayedExpansion
set FileMask=C:\1_test\*.csv
set OutFile=C:\0_test\combined.csv
For %%F in ("%FileMask%") do (
	for /F "delims=" %%H in ('type "%%F"') do (
		>"%OutFile%" echo %%H ,File_Name
		goto :Combine
		)
	)
)
:Combine
for %%F in ("%FileMask%") do (
	more +1 "%%F" >>"%OutFile%"
	)

Open in new window


I'm attaching a couple .csv files that have data in fields that cause issues during combine. If you combine these two files with your program you'll see the issues.
test_1.csv
test_2.csv
ASKER CERTIFIED SOLUTION
Avatar of oBdA
oBdA

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Rexx

ASKER

Nice work. I did drop the first four lines and saved it as a .ps1.

What would change to get just the file name without the path?
Just replace all occurrences of 'Expression={$File.FullName}' with 'Expression={$File.Name}' (lines 16, 23, 30 in the 'batch' script above).