0

I want to merge all .docx files within a folder with a .bat file (no Powershell, as I'd need to make sure the target computers are all set to allow powershell scripts). It would be great if the output file was named after the parent folder name.

There is a command line utility for merging docx files here:

https://github.com/jamessantiago/DocxMerge

It needs the following syntax: docxmerge.exe -i $input_files -o $output_file_name

Simple version (should work once/if docxmerge fixes the sorting bug = unlikely)

@echo off & setlocal enabledelayedexpansion
cd %1
set files=

for %%i in (*.docx) do set files=!files! "%%i"

set name=
for %%i in (.) do set name=%%~nxi

DocxMerge.exe -i %files% -o "%name%.docx" -f

=> works 90%, but: the output.docx contains the documents in the wrong order:

%files% if echoed gives me the filenames in the correct, alphabetical order. For some reason though, after docxmerge runs it gives me the following order:

Example for 10 page document

Page 1  

Page 10  

Page 9  

...  

Page 2

========

I need to reorder from the current alphabetical list as follows:

  • file 1
  • rest of the files in reverse order (i.e. 10, 9, ..., 2)

============================================================

Workaround version:

@echo off & setlocal enabledelayedexpansion

set name=
for %%i in (.) do set name=%%~nxi

del /f %name%.docx

set files=
set firstFile=

for %%i in (*.docx) do (
    if [!firstFile!]==[] (
        set firstFile="%%i"
    ) else (
        set files="%%i" !files!
    )
)

set files=%firstFile% %files%

DocxMerge.exe -i %files% -o "%name%.docx" -f
3
  • 2
    This will never work. Docx files are actually ZIP files. If you don't believe me, rename your docx to zip and open it up! You can't simply add zip files together. Even if this was the doc format, this is also true. Both file formats have headers and footers. At best, you would need a utility to merge the files together.. I know of no such utility although it might exist. Nov 11, 2020 at 1:32
  • I know, that's why said utility was already in the OP ;-)
    – Sayuuk
    Nov 11, 2020 at 6:54
  • Do they have to be merged in alphabetic order? If so, you can just reverse the output of the dir command: dir /b /o-n *.docx. Or else use set "row=%%x !row!" instead. The encoding issue might be fixed by setting a different codepage: chcp 65001
    – Berend
    Nov 11, 2020 at 8:22

3 Answers 3

1

You don't need to print the file names to a text file just to read it back. You can just collect the names in a variable with a for loop.

This script should work:

@echo off & setlocal enabledelayedexpansion
cd %1
set files=

for %%i in (*.docx) do set files=!files! "%%i"

DocxMerge.exe -i %files% -o "%~n1.docx"

It expects the folder containing the .docx files as its first and only argument, which means you can just drag-and-drop the folder onto the batch file.

The name of the folder given in the argument will be used as the name of the output file. This is achieved by expanding the argument to a file name only with %~n1.

If you want to place the batch file in the folder containing the .docx files and not use an argument you can obtain the name of the current folder with

set name=
for %%i in (.) do set name=%%~nxi

If the files are processed in the wrong order you can reverse the order by replacing set files=!files! "%%i" with set files="%%i" !files!.

Edit:

The wrong order definitely sounds like a bug in DocxMerge. You can work around that by storing the first file in a seperate variable and then prepending that value to the rest of the files after the for loop:

@echo off & setlocal enabledelayedexpansion
set files=
set firstFile=

for %%i in (*.docx) do (
    if [!firstFile!]==[] (
        set firstFile="%%i"
    ) else (
        set files="%%i" !files!
    )
)
set files=%firstFile% %files%

set name=
for %%i in (.) do set name=%%~nxi

DocxMerge.exe -i %files% -o "%name%.docx" -f

To delete the result of previous merges so it isn't included in a new merge just move

set name=
for %%i in (.) do set name=%%~nxi

above the for loop and add if exist "%name%.docx" del "%name%.docx"

2
  • What exactly do you get when you echo %files% vs what you expect? For me the output is "A.docx" "F.docx" "E.docx" "D.docx" "C.docx" "B.docx", which is exactly what you wanted, or did I misunderstand?
    – seabeast
    Nov 12, 2020 at 7:17
  • I didn't realize the output.docx was being merged as well, making docxmerge unable to access the file. I've added a line at the beginning, removing output.docx with del /f %name%.docx and moving the set to the beginning. It's working perfectly now!
    – Sayuuk
    Nov 12, 2020 at 8:09
1

I have a folder which has many subfolders in it containing Word documents. I want to merge Word documents within a each folder and then merge the resulted merged documents created in each of folders into one large document.

The below code is merging documents in a folder and when I perform a loop and add this above for loop to go in each subfolder and create separate merged document, it says "-i is required". Why do I get this message?

code below:

@echo off & setlocal enabledelayedexpansion

set /A C=0    
FOR /R %%a in (.) do (    
  pushd %%a    
  echo In directory:    
  cd    
  SET firstFile=    
  SET files=

  FOR %%X in (*.docx) DO (    
  IF [!firstFile!]==[] (    
          SET firstFile="%%X"    
    ECHO yes        
      ) ELSE (    
          SET files="%%X" !files!       
    ECHO next    
      )    
   )

   ECHO ifclose    
     SET files=%firstFile% %files%    
 set /A C=C+1

 DocxMerge.exe -i %files%  -o "doc%C%.docx" -f

 pause    
 rem leave the directory    
 popd    
 pause    
)
0

The wrong order is a very common issue. Instead of modifying scripts and commands every time, it is better to rename the source files: i use advanced renamer with this simple in-built method advanced renamer method. In this way any program and script will recognize the right order of pages and files, since 002 is always before than 010.

You must log in to answer this question.

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