Merge Selected Files (Batch)

Discuss and announce Total Commander plugins, addons and other useful tools here, both their usage and their development.

Moderators: Hacker, petermad, Stefan2, white

User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Merge Selected Files (Batch)

Post by *Balderstrom »

  1. Select Files
  2. Press Button
  3. Selected Files will be Merged
Create a User-Command or Button wrote:Command: cmd.exe /c MergeFiles.cmd
Parameters: %S
Parameter (Argument) Definitions:
  • /D : Delete Source Files after merge.
  • /F : Force overwrite an existing OutFile.ext.
  • /M=PATH : Move source files to "PATH"
  • /O=NAME : Final Name of merged files. (Can be %1)
Parameter (Argument) Notes:
  1. /O=%1, the First Selected File will be used as the OutFile (and you will NOT be prompted to overwrite).
  2. If you use, /O=%1 /M=SomePath, then your original sources will be backed up to "SomePath",
    And the OutFile will be named after the first Selected File.
  3. The /M="PATH" parameter takes precedence over the /D (delete source) parameter.
    Thus if both are provided as parameters, the files will be moved - not deleted.
Example Commands (with Arguments):
  • cmd.exe /c MergeFiles.cmd /O=OutFile.ext
  • cmd.exe /c MergeFiles.cmd /F /O=OutFile.ext
  • cmd.exe /c MergeFiles.cmd /D /F /O="A File With Spaces.log"
  • cmd.exe /c MergeFiles.cmd /D /F /O=%1
  • cmd.exe /c MergeFiles.cmd /O=%1 /M=BAK
Note: The order of the Arguments above are not important.

Code: Select all

@ECHO OFF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
::   MergeFiles.cmd v1.95      (Balderstrom, 2012)
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: Change to "SET GetFileName=1",
::      It will be ignored if you use the /O Parameter.
SET GetFileName=0
::
:: IF GetFileName is 1 - You will Prompted for the Final MergedFileName.
:: If you Input an existing filename, Prompt Permission to Overwrite it.
:: IF Overwrite is allowed, Also prompt to delete existing Source Files.
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

SET UnderScore=_
SET MoveSource=""
SET QueryDelete=0
SET DeleteSource=0
SET ForcedOverWrite=0
SET OutFile=""
SET OutOldF=""
SET AddFileHeader=
SET FileList=
SET FileList_Count=0

:_READARGS
SET NextArg="%~1"
IF %NextArg%=="/D" SET DeleteSource=1&SHIFT&GOTO:_READARGS
IF %NextArg%=="/F" SET ForcedOverWrite=1&SHIFT&GOTO:_READARGS
IF "%NextArg:~1,2%"=="/M" CALL:_SETFILE MoveSource "%~2" &SHIFT&SHIFT&GOTO:_READARGS
IF "%NextArg:~1,2%"=="/O" CALL:_SETFILE OutFile "%~2" &SHIFT&SHIFT&GOTO:_READARGS
IF "%NextArg:~1,2%"=="/H" CALL:_SETSAFESTRING AddFileHeader %~2 &SHIFT&SHIFT&GOTO:_READARGS
IF %NextArg% == "%~1" CALL:_ADD_FileList "%~1"&SHIFT
IF "%~1" NEQ "" GOTO:_READARGS

FOR /D %%D IN (%FileList%) DO CALL:_VERIFYFILES %%D

IF %FileList_Count% LSS 2 CALL:_ERRORMSG "Select at least 2 files to Merge."
IF %OutFile%=="/O" SET OutFile="%~1"&SET ForcedOverWrite=1

:_RENAME_MASTER
  SET Master="%~n1%UnderScore%_MERGED%~x1"
  IF EXIST %Master% SET UnderScore=_%UnderScore%& GOTO:_RENAME_MASTER

IF -%AddFileHeader%-==-- GOTO:_LOOP_FileList
:_CreateTempHeadersFolder
MKDIR "%UnderScore%MergeFilesTempHeaders%UnderScore%" 1>NUL 2>&1
IF %ERRORLEVEL% NEQ 0 SET UnderScore=_%UnderScore%& GOTO:_CreateTempHeadersFolder

:_LOOP_FileList
CALL:_LOOP %FileList%
GOTO:_COPY

:_LOOP
  IF -%AddFileHeader%- NEQ -- CALL:_CREATE_HeaderFiles "%~1" %AddFileHeader% %UnderScore%MergeFilesTempHeaders%UnderScore%
  IF -%AddFileHeader%- NEQ -- (
    SET CopySTR=%CopySTR% + %HeaderFileName% + "%~1"
  ) ELSE (
    SET CopySTR=%CopySTR% + "%~1"
  )
  SET DelMoveSTR=%DelMoveSTR% "%~1"
  SHIFT
  IF NOT "%~1"=="" GOTO:_LOOP

:_COPY
  COPY /Y %CopySTR:~3% %Master% 1>NUL 2>&1
  IF NOT EXIST %Master% CALL:_ERRORMSG "Merge Failed!"
  ECHO. >> %Master%

IF %GetFileName%==0 GOTO:_MOVE_DELETE_FILES
FOR /L %%L IN (1,1,11) DO ECHO.
:_GET_FILENAME
  IF %OutFile%=="" CALL:_GETINPUT
  IF %OutFile%=="" (
    IF NOT %OutOldF%=="" SET OutFile=%OutOldF%
    SET QueryDelete=1
    GOTO:_MOVE_DELETE_FILES
  )
  IF NOT EXIST %OutFile%  GOTO:_MOVE_DELETE_FILES
  IF %ForcedOverWrite%==1 GOTO:_MOVE_DELETE_FILES
  ECHO.&ECHO.
  ECHO %OutFile% Already Exists!
  ECHO.&ECHO.
  SET PromptExtra=[Press Enter to Overwrite %OutFile%]
  SET OutOldF=%OutFile%
  SET OutFile=""
GOTO:_GET_FILENAME

:_MOVE_DELETE_FILES
  IF NOT %MoveSource%=="" (
    MKDIR %MoveSource% 1>NUL 2>&1
    FOR /D %%F IN (%DelMoveSTR%) DO MOVE %%F %MoveSource% 1>NUL 2>&1
    MOVE /Y %Master% %OutFile% 1>NUL 2>&1
    GOTO:EOF
  )
  IF %QueryDelete%==1 IF %DeleteSource%==0 (
    SET /P QueryDelete=Delete Source Files ^(Y/N^)?
  )
  ECHO %QueryDelete%|FIND /I "Y" 1>NUL 2>&1 && SET DeleteSource=1
  IF %DeleteSource%==1 DEL %DelMoveSTR% 1>NUL 2>&1
MOVE /Y %Master% %OutFile% 1>NUL 2>&1
ECHO "%UnderScore%MergeFilesTempHeaders%UnderScore%"
IF -%AddFileHeader%- NEQ -- RMDIR /S /Q "%UnderScore%MergeFilesTempHeaders%UnderScore%" 1>NUL 2>&1
GOTO:EOF


:_ERRORMSG
  CLS&ECHO.&ECHO.&ECHO.&ECHO [ERROR]: %~1&ECHO.&ECHO.
  PAUSE&EXIT
GOTO:EOF

:_ADD_FileList
IF "%~1" NEQ "" SET FileList=%FileList% "%~1"&SET /A FileList_Count=%FileList_Count% + 1
GOTO:EOF

:_VERIFYFILES
  SET isDir=%~a1
  IF "%isDir%"=="" GOTO:EOF
  IF "%isDir:~0,1%"=="d" CALL:_ERRORMSG "Select Files Only!"
GOTO:EOF

:_SETFILE
SET %1="%~2"
GOTO:EOF

:_CREATE_HeaderFiles
SET HeaderFileName=".\%~3\%~1.tmp"
ECHO.>>%HeaderFileName%
ECHO %~2 '%~1' %~2 >> %HeaderFileName%
GOTO:EOF

:_SETSAFESTRING
SET %1=%~2
GOTO:EOF


:_GETINPUT
IF NOT "%PromptExtra%"=="" ECHO %PromptExtra%
SET /P OutFile=Output File for Merged files?
IF NOT ^%OutFile:~0,1%==^" SET OutFile="%OutFile%
IF NOT ^%OutFile:~-1%==^"  SET OutFile=%OutFile%"
GOTO:EOF
Version 1.90
+ /H= Parameter
Version 1.85
√ BugFix: Error with /D /O=%1, if /O wasn't the last parameter.
* Code Clean-Up.
Version 1.80
+ /M Parameter.
Version 1.75
+ Parameters Added: /O, /D, /F
Version 1.50
Major Update from original 1.0
Last edited by Balderstrom on 2012-08-01, 19:38 UTC, edited 6 times in total.
Fuzz
Junior Member
Junior Member
Posts: 3
Joined: 2011-06-14, 13:44 UTC

Post by *Fuzz »

2Balderstrom
thanks! Very usefull button. Was searching for this for some time! Works perfect for me.
User avatar
Ambaquista
Junior Member
Junior Member
Posts: 64
Joined: 2005-05-27, 11:11 UTC
Location: Luanda, Angola

Post by *Ambaquista »

Nice job.
I work with the freeware program TXTCollector (with a button in the toolbar), but it grabs all the files with the given extension.
I change to your batch
brgds
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

Cool. For some reason I like batch --- I must like suffering :-)

I recently had to do some scripting with AppleScript --- worst language I've ever used, and I've done LISP, Prolog and Assembly (ASM).

Exagerration for comic effect (slightly):
(pseudo AppleScript) ---> with variable x please set it to y as a string if you wouldn't mind so much
cubic
Junior Member
Junior Member
Posts: 82
Joined: 2007-07-18, 12:21 UTC

Post by *cubic »

Ambaquista wrote:Nice job.
I work with the freeware program TXTCollector (with a button in the toolbar), but it grabs all the files with the given extension.
I change to your batch
TXTCollector is VERY poor indeed because it is limited: I want to merge ALL files.
So finally I use this dedicated program: Disk Tools
Last edited by cubic on 2011-08-10, 13:04 UTC, edited 1 time in total.
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

Editor's pick from Brothersoft? Really? Possibly the worst site ever for software. I've had them blocked in my custom google search for years.

Most of those other programs can be accomplished with a quick script, 10-20 lines (kb or 2, instead of 400 to 1000kb). And I certainly wouldn't look to getting any software from a developer that promotes a program to create fake web-traffic (900kb, also note this can be done with about 4 lines of a script *smirk*)

Some disk tools "features" that can be accomplished with 1-2 lines of script.
1) Create huge files to see how text processors can handle them (see File Generator)
2) Create millions of files.

And you drop by MY thread just to let me know my "software" sucks? Compared to a piece of closed-source crap gui on the internet.
Try again.
Fuzz
Junior Member
Junior Member
Posts: 3
Joined: 2011-06-14, 13:44 UTC

Post by *Fuzz »

Balderstrom, +1
r0k
Junior Member
Junior Member
Posts: 4
Joined: 2012-06-20, 14:22 UTC

Post by *r0k »

Hi. Sorry for the thread necromancy.
I just found this batch. Very useful. Just one request, is it possible to have an option to insert the merged filenames in the output file. So if i have file "file1.txt", "file2.txt" ... the output would look like :
file1.txt
<content of file 1>
file2.txt
<content of file 2>
...
This could be useful in some cases.
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

It's doable, will require an additional variable/parameter, creation of said files as a group of "header-files"... making it safe we'd want to check if those files already exist (that we are about to create), else fail.
Then in the main merge section we'd change it so that the newly created header-files are copied before the content itself.
Before the script exits, we'd want to again, check if the new variable-parameter was used (not equal to -1) and clean up those tempoarily created files (delete them).

Note to self: Create temporary "MergeFiles_TempHeaders" Folder, if ErrorLevel, Fail. * Easiest way to check for multiple files existing. Delete folder at end of script.

I'll test the code after work.
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

/H=STRING Parameter Added.

Code assumes, that
1) You don't surround STRING with quotes - it doesn't look very good inserted in between the merged files.
2) Since you shouldn't use quotes around the STRING, you don't use special characters, like &|

Usage Example:

MergeSelectedFiles.cmd /H=***

Output header line would appear like:
*** 'Example File.txt' ***
Fuzz
Junior Member
Junior Member
Posts: 3
Joined: 2011-06-14, 13:44 UTC

Post by *Fuzz »

seems like v1.90 didn't work for me. Returned to previous ver... Is code correct?
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

I did test... apparently in a folder without any other directories.

The recommended asterix '*' for the /h parameter, causes the FOR /D loop to parse it as a wildcard, and turns the FOR /D loop into a "Loop through all foldernames in the current directory" ... which causes the VerifyFiles check to fail, as it now matches a folder --- which shouldn't be selected.
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

V1.95 Fix for added /H parameter, when '*' was used as a header spacer character. For /D Loop broke.
*BLINK* TC9 Added WM_COPYDATA and WM_USER queries for scripting.
User avatar
EricB
Senior Member
Senior Member
Posts: 357
Joined: 2008-03-25, 22:21 UTC
Location: The Netherlands

Post by *EricB »

Hi Balderstrom,

I also use this batchfile sometimes, very useful for merging textfiles. The 1.95 version does not function correctly anymore. Running from button it just flashes shortly with no output. When run directly from the command line it renders "-==-- was unexpected at this time", which would explain it does not work from button press. Apparently the statement "-%AddFileHeader%-==--" is not recognized.

Regards, EricB
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

IF you change:
IF -%AddFileHeader%-==--
TO:
IF -%AddFileHeader%- EQU --

Does that work? I'm guessing it's pre-Win7? I haven't noticed any of my old win2K/winxp scripts to have compatibility issues since I switched to Win7, but then that particular syntax I never used in older scripts either.
*BLINK* TC9 Added WM_COPYDATA and WM_USER queries for scripting.
Post Reply