0

I need the equivalent of the shell command xargs < list.txt cat -- > compiled.txt as a Windows batch file.

There is a directory full of text files (about 50 to 500 files) that I need to concatenate into one file. The order is important. The files can't be named in asciibetical order, because the natural order is not the order it should be compiled in the target file.

I had the the idea to name the source files like $DISREGARD1_$SECOND-ORDER_$FIRST-ORDER_$THIRD-ORDER_$DISREGARD2.txt and do some voodoo with it, but I think for my use case it is simpler and less volatile to maintain an ordered list. Concatenating from a list is very easy with xargs and cat. How do I do it with a .bat file on Windows?

I need it as an idempotent batch file so that the user can click on it. In the target file should be no command output, superfluous carriage returns or anything else that's not in the sources (i.e. like if the files were binary).

Bonus question: It would be great to allow remarks in the list file (empty lines not allowed in order to limit complexity). I'd do that on shell with sth. like grep -v ^# < list.txt | xargs cat -- > compiled.txt. Any chance to get this into a .bat file as well?

2 Answers 2

2

This should do it:

@echo off
REM create empty result file
copy nul results.txt /y

REM iterate over list skipping #entries and copy binary
for /f "usebackq delims=" %%F in (`findstr /R /V "^#" list.txt`) do (
 copy /b results.txt+"%%~F" results.txt 
)

Syntax as it's batch file, if you want to execute directly from cmd line change %%F to %F

2
  • Accepted this answer, because it also solves the remarks thing. With the learnt lessons on batch files through this question, I am able to combine your script with the script by @grawity into one that doesn't copy everything on each iteration. Jun 16, 2014 at 13:11
  • @JoBo I used it mainly to show different options available. Please also note that the order is important (dest+source dest, source+dest dest will not work) and it's recognized as append and optimized by cmd interpreter so it's pretty efective
    – wmz
    Jun 16, 2014 at 15:32
2

Use a for loop:

@echo off

( for /f "tokens=*" %%i in (list.txt) do type "%%~i" ) > compiled.txt
8
  • 1
    I have created a test case with for i in $(seq -w 0000 9999); do PREFIX=$(pwgen 8 1); echo $i > $PREFIX-$i.txt; echo $PREFIX-$i.txt >> list.txt; done. Result are files with random $PREFIX and serial suffix ($i) and with suffix as each file's content. xargs/cat generates a file with 0000\n0001\n0002\n and so forth. This batch file produces \r\n\C:\concat>type "jiesaeyi-0000.txt"\r\n0000\r\n\r\nC:\concat>type "sohsaiph-0001.txt"\r\n0001\r\n\r\n and so forth. Jun 16, 2014 at 9:36
  • 1
    NOTE: In the above example %%i is used. A %% variable is only used when inside a batch file. If the command is executed from the commandprompt directly, use %i instead (on both occassions)
    – LPChip
    Jun 16, 2014 at 9:46
  • actually \n\r\n (LFCRLF) after each four digit number Jun 16, 2014 at 9:47
  • 1
    Ah, yeah, I assumed you'd use this as just a part of existing batch script, with @echo off and all. Updated. Jun 16, 2014 at 12:19
  • 3
    @JoBo To skip lines containing # and to handle a file list name that contain spaces, change the for command like this: for /f "usebackq eol=# delims=" %%i in ("my list.txt") do type "%%~i"
    – and31415
    Jun 16, 2014 at 13:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .