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
EricB
Senior Member
Senior Member
Posts: 357
Joined: 2008-03-25, 22:21 UTC
Location: The Netherlands

Post by *EricB »

I'm running Win7 x64 Pro.
Changing the statement as proposed does render following error: "- was unexpected at this time."

Regards, EricB

Edit:
using %AddFileHeader%-- EQU -- (and also in 3 other instances with NEQ) seems to work. Apparently characters directly preceding a variable is not accepted by the processor.

Edit2:
but when I use /H=*** when calling the batchfile it again does not work. Message: -- was unexpected this time.
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

Heres a slightly changed, added a Goto:EOF into :_LOOP_FileList
which may of been triggering an erroneous/false error message.

If you could try this, and tell me what your
1) Button| Command, Parameters
2) Source path, source filenames.

Code: Select all

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%- EQU -- 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:EOF



:_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
  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
*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 »

I ran this in a folder d:\tools in a cmd window as "mergefiles file1.txt file2.txt" (which should work OK, isn't it?).

Last output line is d:\Tools>IF EXIST "_ _MERGED" SET UnderScore=__ & GOTO:_RENAME_MASTER
- was unexpected at this time.

The merged text file is now not created and two temp folders _ MergeFilesTempHeaders_ and __ MergeFilesTempHeaders__ (including nasty spaces in their name) now remain.

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

Post by *Balderstrom »

Odd, is it possible your file has a blank space after the underscore in this ?
"SET UnderScore=_ "

There definitely shouldn't be spaces in those Folders, and there definitely shouldn't be a space in between the underscores in
IF EXIST "_ _MERGED" ---> IF EXIST "__MERGED"
*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 »

Indeed, file had extra blank for underscore variable. I copied/pasted your code and because of this every EOL marker was preceded by a space...

After correction of this everything works as expected. Running with only two files as argument does a correct merge and using /H=*** now indeed inserts a correct separator.

Well done!

Regards, EricB
User avatar
EricB
Senior Member
Senior Member
Posts: 357
Joined: 2008-03-25, 22:21 UTC
Location: The Netherlands

Post by *EricB »

Follow-up:

If I define the button as follows

TOTALCMD#BAR#DATA
cmd.exe /C %COMMANDER_DRIVE%\Tools\mergeFiles.cmd /H=---
%S
%COMMANDER_PATH%\wciconex.dll,77
Merge Selected Files


-1

The merge runs correctly, but the resulting filename obtains name __merged instead of assuming part of the filename of the first file in the selection.

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

Post by *Balderstrom »

Yeah, to assume the first filename as the output we would need to do:
cmd.exe /k mergeFiles.cmd /O="%1"

If you want a separator between the merged files:
cmd.exe /k mergeFiles.cmd /O="%1" /H=---
OR:
cmd.exe /k mergeFiles.cmd /O="%1" /H=***

I'm just not running into any errors on my end, in either folders with no directories (the major glitch after adding /H), nor folders with just files-to-be-merged.

Now if you do use /O="%1" - that will overwrite the first input file (at the end). You might want to also either use /D (force delete source) or
mergeFiles /O="%1" /F /H=--- /M=".\BAK"

: 1st-File-AsName, ForceOverwrite First-File if it exists, Separator, and backup sourceFiles (before overwrite) to .\BAK folder.
*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 »

I was commenting on this because version 1.85 did a merge and then named the resulting output file "name of first file in list"__merged.ext; I kind of missed this in the new version. It is IMO the safest way, because you never loose your originals.

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

Post by *Balderstrom »

Can you test this version, I completely forgot that the old version did the FirstFile__MERGED.EXT - which got munged when I moved the code to create a FileList for the /H param :P

The default output (outfile) should be as it was.
:: Moved ADD_FileList, Rename_Master, and OutFile check/fix into the VerifyFiles routine, which has access to the required %1 parameter.

Code: Select all

SET GetFileName=0
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::_VERIFYFILES "%~1"&SHIFT
IF "%~1" NEQ "" GOTO:_READARGS

IF %FileList_Count% LSS 2 CALL:_ERRORMSG "Select at least 2 files to Merge."

IF -%AddFileHeader%- NEQ -- CALL:_CreateTempHeadersFolder


CALL:_LOOP %FileList%
GOTO:EOF

:_LOOP
  IF -%AddFileHeader%- NEQ -- CALL:_CREATE_HeaderFiles "%~1" %AddFileHeader%
  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
  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


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

  IF "%~1" NEQ "" SET FileList=%FileList% "%~1"&SET /A FileList_Count=%FileList_Count% + 1
  IF %FileList_Count% GTR 1 GOTO:EOF
:_RENAME_MASTER
  SET Master="%~n1%UnderScore%_MERGED%~x1"
  IF EXIST %Master% SET UnderScore=_%UnderScore%& GOTO:_RENAME_MASTER
:_FIX_OUTFILE
  IF %OutFile%=="/O" SET OutFile="%~1"&SET ForcedOverWrite=1
GOTO:EOF

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

:_CreateTempHeadersFolder
SET HeaderFolderName=%UnderScore%MergeFilesTempHeaders%UnderScore%
MKDIR %HeaderFolderName% 1>NUL 2>&1
IF %ERRORLEVEL% NEQ 0 SET UnderScore=_%UnderScore%& GOTO:_CreateTempHeadersFolder
GOTO:EOF

:_CREATE_HeaderFiles
SET HeaderFileName=".\%HeaderFolderName%\%~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
User avatar
EricB
Senior Member
Senior Member
Posts: 357
Joined: 2008-03-25, 22:21 UTC
Location: The Netherlands

Post by *EricB »

Yes, this version indeed creates the FirstFile__merged.ext again, either when run from CMD window or as a button command.

Also tested the /H parameter for both situations which still works as expected.

When FirstFile__merged.ext already exists, the new result obtains an extra underscore in its name, nice one!

Seems that this version can be de-ECHO-ed and published.

One suggestion which may be (or may not be) of value:
the batch file is now setting all kinds of env vars. When running it more times from the same CMD window this will cause some trouble. How about cleaning up / resetting the env vars at the end? This way the batch could also be used stand alone, without TC.

Regards, EricB
Post Reply