Reputation: 25
I have a bunch of .csv
files that are generated externally and sent to me periodically. they each contain a single row of text with 31 "columns". None of them, however, have any kind of EOL
(no LF by itself or with CR), so when I attempt to combine any of these files, I get more columns on the same row, instead of a row for each file.
I would like a way to automatically add this to the end of each of these files in a batch, with the outputs having the same filename as the original file, potentially with the addition of a character at the beginning of the name so I new this process was completed. Ex: originalFile.csv>> 1_originalFile.csv
.
I had attempted to create a file called "eol.csv
" that was simply (LF and CR), and create a batch that would add that to the end of all of my files, but as I am a novice to writing batch files, I was significantly unsuccessful.
If it were possible for this to execute on each file as it were dropped into a folder, that would be even better.
Thanks for any thoughts on this!
Upvotes: 1
Views: 1933
Reputation: 34979
There are several methods to append a line-break to (the last line of) a file if not yet present:
findstr /V "$" "data.csv" > nul && echo/>> "data.csv"
This inverse (/V
) search matches the last line only when it is not terminated by a line-break. In such case &&
lets the following command execute, which just appends a line-break.
Restrictions:
find
:
< "data.csv" find /V "" > "data.csv.tmp" && move /Y "data.csv.tmp" "data.csv" > nul
This search matches all lines, find
appends a line-break to every returned line, even for the last one when there is none. A temporary file is required since it is not possible to read from and write to the same file. If no errors occur, &&
lets the next command execute, which moves the temporary file onto the original one.
Restrictions:
more
:
more "data.csv" > "data.csv.tmp" && move /Y "data.csv.tmp" "data.csv" > nul
This just returns all lines; more
appends a line-break to every returned line, even for the last one when there is none. A temporary file is required since it is not possible to read from and write to the same file. If no errors occur, &&
lets the next command execute, which moves the temporary file onto the original one.
Restrictions:
sort
:
sort "data.csv" /+65535 /REC 65535 | sort /+65535 /REC 65535 /O "data.csv"
This just returns all lines; sort
appends a line-break to every returned line, even for the last one when there is none. Surprisingly, no temporary file is required (I tested with a ~ 30 MB file without data loss due to I/O collisions). Nevertheless, this is likely the slowest method here because of the pipe (|
).
The key is to set a character position for sorting that is beyond the data. In such cases, sort
seems to simply revert the whole file; this is the reason for using two sort
commands. But I tested it just very quickly with one file on Windows 7, so you should be cautious with this.
Restrictions:
All of the above approaches can easily be implemented in a for
loop in order to be applied to multiple files; simply replace data.csv
with the for
meta-variable then (demonstrated on variant 1. here):
for %I in ("*.csv") do @(findstr /V "$" "%~I" > nul && echo/>> "%~I")
Remember that the %
-signs need to be doubled when using this code in a batch-file.
Upvotes: 0
Reputation: 975
This will search all .csv
file names for the string _fixed
, and on any who fail to have it, will insert a blank line and rename it. Of course replace the pathToWherever
with the correct path for you, and the /s
option can be added to allow searching in subfolders in the named path too.
@echo off
for /r "C:\pathToWherever\" %%G in (*.csv) do (
echo %%G | findstr /c:"_fixed" || (
echo:>>%%G
ren "%%G" "%%~nG_fixed.csv"
)
)
Upvotes: 1
Reputation: 130919
The FINDSTR regular expression $
recognizes end of line as the position immediately before a carriage return. So findstr /v $
will only match lines that do not contain a carriage return. You can use this fact to append carriage return/linefeed to only files that need it, without having to rename any files.
The following one liner from the command line is all you need:
for /f "eol=: delims=" %F in ('findstr /m /v $ *.csv') do @(echo()>>"%F"
Double up the percents if you put the command within a batch script.
Upvotes: 4
Reputation: 14325
Since all echo
s end in a CRLF, and you can use echo/
to echo a CLRF by itself, you can simply use output redirection to append a CLRF to each of the csv files.
If you want to run this on a bunch of files that you've dragged and dropped onto the script, it would look like this:
@for %%A in (%*) do echo/ >>%%A
That one line is the entire script, by the way.
Upvotes: 1