0

I have/found a windows batch script that will combine csv files from all sub-directories. It works great in Windows 10 but when I run the script in Windows 7, all the files are out of order. How do I force the order in which to combine the csv files?

echo @off
for /r %%i in (*.csv) do (
if not %%~nxi == output.csv (
echo %%~nxi >> output.csv
echo %%i
echo %%~nxi
type "%%i" >> output.csv
echo. >> output.csv
echo. >> output.csv
)
)
  • 2
    Your batch has no explicit ordering implemented, the only reason I can think of, is that one file system might be ntfs while the other is fat/samba/whatsoever. Ntfs sorts inherently alphabetcally. –  Dec 22 '18 at 01:31
  • 1
    @LotPings the order in NTFS is just [*approximately alphabetical for US-English* and *It's not very alphabetical for most other languages*](https://blogs.msdn.microsoft.com/oldnewthing/20140304-00/?p=1603) – phuclv Dec 22 '18 at 10:39
  • You may consider accepting an answer (that works the best). – double-beep Feb 12 '19 at 16:00

4 Answers4

2

Just a little change to your code will do the job:

@echo off
FOR /F "usebackq delims=" %%i IN (`dir /s /b /O:N *.csv`) do (
    if not "%%~nxi" == "output.csv" (
        echo %%~nxi >> output.csv
        echo %%i
        echo %%~nxi
        type "%%i" >> output.csv
        echo. >> output.csv
        echo. >> output.csv
    )
)

Point is to use another command's out -- use dir to control the sorting order.
/b for clean output by dir
/O for ordering, N -- name.
check FOR /? and dir /? for more details.

PS: you may wanna use:

echo %%~dpnxi >> output.csv

instead of line 4's echo %%~nxi >> output.csv , to show full path of each file in your output.csv.

Til
  • 5,150
  • 13
  • 26
  • 34
1

This is just a slight modification to POW's answer that should give you better performance. This technique keeps the file open for writing. When you use the append multiple times, it is opening and closing the output file. So the file pointer has to be reset every time it outputs to the file.

@echo off
(FOR /F "usebackq delims=" %%i IN (`dir /s /b /O:N *.csv`) do (
    echo %%~nxi
    echo %%i >con
    type "%%i"
    echo.
    echo.
)
)>output.tmp
rename output.tmp output.csv
Squashman
  • 13,649
  • 5
  • 27
  • 36
  • Using a different name **while** processing wouldn't avoid including a **previous** output.csv. What about filtering with `dir /s /b /O:N *.csv ^|findstr /IVEC:"output.csv"` ? –  Dec 23 '18 at 18:01
  • 1
    @LotPings, I guess I shouldn't assume they were creating a new file. So I guess I would just put a delete statement at the beginning. That is also assuming they are not constantly appending to the file. – Squashman Dec 24 '18 at 03:36
0

Here is another possible solution:

@echo off

for /R %%A IN (*.csv) do (
     if not "%%~nxA"=="output.csv" (
           (echo %%~fA && type "%%~fA" && echo. && echo.)>>output.csv
           echo Processed: %%A
           echo %%~nxA
     )
)

with much less code.

  • Using /R option with for to loop through subfolders in %cd%.
  • We want to parse ALL csv files so, we specify it in parenthesis with (*.csv).
    • Then, we check if csv file currently processed is output.csv.
      • If not, then we append full path of the csv ("%%~fA") file, its content (type "...") and two newlines (echo.) to output.csv. This condition is not really required, but added to be on-topic with the question. Also, if you don't want to append full path to output.csv, but filename and extension only just replace %%~fA with %%~nxA.
      • After that, we echo current file processed and its filename and extension.

      • If file currently processed is output.csv, then we repeat the loop.
  • Now, output.csv has the contents of all csv files in all subdirectories.

So, now open a new cmd and type the following commands. Read the output carefully:

  • for /?
  • if /?
  • echo /?
  • type /?

Some suggestions for further reading:

double-beep
  • 5,031
  • 17
  • 33
  • 41
  • 3
    Out of curiosity why do you always use the conditional operator with all your code instead of using just the single ampersand for a command separator? Or just put each command on it's own line in a code block? – Squashman Dec 22 '18 at 18:07
0

Thanks to all of you for your help. After reading all the responses, I realized that I could get around the windows sorting problem by sorting into a second file and then reading it from there.

dir /b /s /O:N *.csv | sort > file.txt
for /f %%A IN (file.txt) do (
if not %%~nxA == output.csv (
echo %%~dpnxA
echo %%~nxA >> output.csv
type %%A >> output.csv
echo. >> output.csv
echo. >> output.csv
)
)

Again, thank you for all your help.