Batch concatenate multiple .ts files to single file in order - batch-file

I am trying to merge multiple .ts files into a single one.
The below script merges files in order if file numbers are less than 10 i.e. A1.ts, A2.ts, ...., A9.ts:
copy /b *.ts joined_files.ts
However, when file numbers are greater than 100, they get merged in the order A1.ts, A10.ts,..., A2.ts, A20.ts, and so on. (Not numerically as expected)
To deal with this issue, I am trying to use a for loop and a variable name iterating over the numbers as below:
:MainProcessNew
set "BaseName=A"
set "FileNumber=1"
:FileNameLoop
set /A FileNumber+=1
copy /b "%BaseName%%G%.ts" joined_files.ts
if exist "%BaseName%%FileNumber%.ts" goto FileNameLoop
I found this link to be relevant but I could not follow: Link
I am very new to batch scripts. Please help me out !

One thing you can do is to extract the numbers. In your case it seems easy enough as you have a pattern which is basename, number, extension.
So we can then extract all the numbers, match them with each other to find the highest number, then sort them using for /l:
#echo off
set max=
set "bn=A"
setlocal enabledelayedexpansion
for /f "delims=" %%i in ('dir /b "*.ts"') do (
set "nm=%%~ni"
set "nm=!nm:%bn%=!
if not defined max set max=!nm!
if !nm! gtr !max! set max=!nm!
)
for /l %%n in (1,1,%max%) do if exist %bn%%%n.ts echo %bn%%%n.ts
This will simply print each name to the screen to show you that it is able to sort it. In your case you can then change the last line to:
(for /l %%n in (1,1,%max%) do if exist %bn%%%n.ts type %bn%%%n.ts)>joined_files.ts

Related

How to merge files with partial matches of filename to numeric range in ImageMagick

There are a list of numbered files:
out0001.tif, out0002.tif, ..., out0100.tif, out0101.tif, ..., out2300.tif
And I'd like to merged them into layered tif (using ImageMagick convert) that should contain 100 layers. E. g.
merged_1-100.tif, merged_100-200.tif, ...
When I run the following cmd, it try to group all tifs in one huge, but I need only first hundred:
convert out00??.tif out0100.tif -adjoin merged_1-100.tif
What I need to modify in the command?
I found a solution using a batch file.
#echo off
set file_list=
set /a start_index=1
set /a finish_index=100
for /l %%G in (%start_index%,1,%finish_index%) do call :make-filelist %%G
rem Check
echo %file_list%
pause
rem Make conversion
convert %file_list% -adjoin merged_%start_index%-%finish_index%.tif
goto :eof
:make-filelist
rem Add leading zeros
set "fn=0000%1"
set "fn=%fn:~-4%"
rem Add filename to list of files
set "file_list=%file_list%out%fn%.tif "
goto :eof
It allows using any range of file indexes. To do so it is necessary to change start_index and finish_index.
This solution process all files existent on disk and automatically generates the correct (ordered) names for the output files.
#echo off
setlocal
set "hundred=100"
:nextHundred
if not exist out%hundred:~1%01.tif goto :EOF
echo Merging hundred %hundred:~1%
set /A "next=hundred+1"
convert out%hundred:~1%*.tif[0-99] out%next:~1%00.tif -adjoin merged_%hundred:~1%01-%next:~1%00
set "hundred=%next%"
goto nextHundred
I have not tested this solution because I have not convert application nor data files. This solution relies on the "convert out*.tif[0-99] will get the first 100 files in alphabetic order" comment posted by the OP.

In a Windows 10 batch file, is there a way to extract only the last total files count?

From a dir command that displays a number of sub-folders within a main folder, I am trying to extract the total number of files only. I am trying to use the FIND command with the string "File(s)", however this lists all of the file totals for each of the sub-folders, in addition to the overall total on the last line. I would like to limit my extraction to only this overall total, and none of the sub-folder file counts.
Whilst I've provided a simple one liner already in the comment section, it does not technically provide a method of doing what you wanted. The task you've explained is really to retrieve a substring of the last but one line of output from the DIR command with its /S option. This method prevents the need to use the FIND command to search for the language dependent string File(s) too.
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "MainFolder=C:\Users\CoastalGuy\Documents"
Set "CommandLine=Dir "%MainFolder%" /S /A:-D"
Set "Last="
Set "LastButOne="
For /F Delims^=^ EOL^= %%G In (
'%CommandLine% 2^>NUL'
) Do (
If Defined Last (
SetLocal EnableDelayedExpansion
For /F "Tokens=1 Delims= " %%H In ("!Last!") Do (
EndLocal
Set "LastButOne=%%H"
)
)
Set "Last=%%G"
)
If Defined LastButOne (
Echo %LastButOne%
Pause
)
For the specific task you've posted, this script is a little over the top, but I've tried to create it more like a template, so that you could more easily adapt it for similar tasks, (by changing the variable values on lines 4 and 5, and modifying the Tokens and Delims values in the inner For /F loop as required).
Found this simple result on an internet search:
After doing a dir /s of the main folder and then exporting a file (Files.txt) of each of the file results using FIND "File(s)", the following command extracts just the last line of that file, which has the grand total of Files from all sub-folders.....
For /F "UseBackQ Delims==" %%A In ("Files.txt") Do Set "lastline=%%A"
Echo - %lastline%
Works Great,
Thanks,

batch Loop through file in folder

all, I'm a newbie with a little knowledge about scripting.
I did this .bat that work perfectly:
for /l %%x in (1, 1, 4) do (
echo %%x
type A%%x.xml + tail.xml >> v%%x.stage
)
It does the loops 4 times, merging the xml files inside the folder. The .bat is in the same folder as the xml to merge.
But I need to edit manually the number 4 if I want to perform a loop of 10.
Is there any way to do a loop using the amount of file in the folder?
Let's say there are 15 .xml files in the folder so the loop will run 15 times.
I've tried different loop codes that I've found on stack overflow, but I wasn't able to make them work :(
can you help me, please?
many thanks
UPDATE:
thanks #Squashman, so my code should be something like this now right?
for %%x IN (*.xml) do set /a count+=1
echo %%x
type A%%x.xml + tail.xml >> v%%x.stage
If the range of numbers is guarantied to be contiguous,
Squashman's suggestion will work well.
To get the highest number independent of any possible gaps, you could use:
:: Q:\Test\2018\12\18\SO_53837368.cmd
#Echo off&SetLocal EnableDelayedExpansion
set "Max=0"
For /f "delims=a." %%A in ('Dir /B "a*.xml"') do (
Set /A "Num=%%A"
if !Num! gtr !Max! set "Max=!Num!"
)
Echo Max number is: %Max%
it splits the filename between the leading a and the dot from the extension keeping the sole number.
The Set /A is used to exclude possible mismatches with nonnueric values.

Setting variable by trimming content of other variable

i have a problem, i need a code as in title. purpose of the script: i need to copy the file with a different language code, f.e. XXX_x_xYYY_EN_xx to XXX_x_xYYY_ES_xx and XXX_x_xYYY_DE_xx. So far i have this, but it does not work:
setlocal enableDelayedExpansion
for /l %%H in (1,1,2) do (
set endf[%%H]=!fName[%%H]:*_EN_=!
set trim[%%H]=_EN_!endf[%%H]!
set beginf[%%H]=!fName[%%H]:%trim[%%H]%=!
)
fName is set elswere, its something like this
fName[1]=XXX_x_xYYY_EN_xx
fName[2]=XXXXX_x_xYYYY_EN_x
Everything works except the set beginf(it spits out "beginf[1]=fName[1]:="), i've tryed myriads of % nad ! combos. Fun fuct it works in this case (other script, same puprose but work for only one file in directory, i'd like to make it more versatile):
set beginf=!NAME:%langcode%=!
help :) thanks!
So you have two diferent conversions for two array elements, isn't it? So you just need to match each filename with its corresponding conversion, right?
Something like this, perhaps?
set "conv[1]=ES"
set "conv[2]=DE"
for /l %%H in (1,1,2) do (
for %%c in (!conv[%%H]!) do set "newName[%%H]=!fName[%%H]:_EN_=_%%c_!"
)
I suggest you to read this answer.
EDIT: New method added
This code do exactly the same than the one in your posted answer:
#echo off
setlocal EnableDelayedExpansion
for %%a in (*.xml) do (
set "fName=%%a"
for %%c in (ES DE PL) do (
copy "%%a" "!fName:_EN_=_%%c_!"
)
)
A comparison of your code vs. this one:
You really not need an array of file names. If you create the array just to process its elements once with no further processing, then you are wasting the space occupied by the array. You may do the same thing using an individual file name variable.
Also, you not need an array of conversions. If you just want to repeat a command with several conversions, then it is much simpler to use a list of conversions instead.
It is a bad idea to use special characters as FOR replaceable parameters (where the documentation specifies a letter). Batch files are intrinsically cryptic, so there is no need to include additional complexities...
If you just want to process all files (no rename they) then it is simpler to use a plain for command instead of a for /F one on a 'dir /B' command. The second form requires to execute an additional copy of cmd.exe program and to create a temporary disk file...
If the newfName (array) variable is used just to execute the copy command in the next line, then such a variable is (again) a waste of space. You may create the new name in the copy command itself.
I found the solution :)
Full script with file counting below:
#echo off
setlocal enableDelayedExpansion
set /a count=0
for /f %%# in ('dir *.xml /b') do (
set /a count+=1
set fName[!count!]=%%~xn#
)
set "conv[1]=ES"
set "conv[2]=DE"
set "conv[3]=PL"
for /l %%H in (1,1,!count!) do (
for /l %%G in (1,1,3) do (
for %%c in (!conv[%%G]!) do (
set "newfName[%%G]=!fName[%%H]:_EN_=_%%c_!"
copy !fName[%%H]! !newfName[%%G]!
)
)
)
loops clarification:
for /l %%H - loops through the fName array
for /l %%G - loops through the lang table (conv) array
for %%c - combine above loops and copy files with changed names
thanks #Aacini for your input, it put me on the right tracks :)

Batch Script assistance needed

Happy Friday Think-Tank!
I need some assistance with a Batch .BAT script. Specifically I need help with some "IF statement syntax"
I have a script that is renaming files. There are two files, one ending in four digits and the other ending in five digits. The files will be renamed with variables I have already pre-set earlier within my script.
So here is a scenario: We have two files in a directory located at
c:\Users\username\Desktop\test-dir
There are two files within test-dir:
file1.12345
file2.1234
A four digit ending is one variable type (VAR1), whereas a file ending in five digits is another variable type (VAR2).
I need an if statement to:
a) read all the files(s) with the chosen directory (without using a wildcard if possible).
b) determine based on the number of digits after the "." which variable to use.
c) once making that determination rename the file with the appropriate variables.
The final re-naming convention is as so: yyyymmddtype.1234/12345
So basically it would use the datestamp variable I already created, the type variable I already created to be injected by the if statement, and append with the original ending digits of the file.
I know this seems like a lot, but I am more so a bash script guy. I have all the elements in place, I just need the if statement and what feels like a for loop of some kind to tie it all together.
Any help would be great!
Thank you!
Sorry, not the option you where asking for. Instead of iterating over the full list checking each file for extension conformance, iterate over a list of patterns that will filter file list, renaming matching files with the asociated "type"
for %%v will iterate over variable list, for %%a will split the content of the variable in pattern and type, for %%f will generate the file list, filter with findstr using the retrieved pattern and rename matching files with the corresponding "type"
Rename command is preceded with a echo to output commands to console. If the output is correct, remove the echo to rename the files.
#echo off
rem Variables defined elsewhere
set "folder=c:\somewhere"
set "timestamp=yyyymmdd"
rem Rename pattern variables in the form pattern;type
set "var1=\.....$;type1"
set "var2=\......$;type2"
set "var1=\.[^.][^.][^.][^.]$;type1"
set "var2=\.[^.][^.][^.][^.][^.]$;type2"
setlocal enableextensions disabledelayedexpansion
for %%v in ("%var1%" "%var2%") do for /f "tokens=1,* delims=;" %%a in ("%%~v") do (
for /f "tokens=*" %%f in ('dir /a-d /b "%folder%" ^| findstr /r /c:"%%~a"') do (
echo ren "%folder%\%%~f" "%timestamp%%%~b%%~xf"
)
)
endlocal
#ECHO OFF &SETLOCAL
set "yyyymmdd=yyyymmdd"
set "VAR1=VAR1"
set "VAR2=VAR2"
for /f "delims=" %%a in ('dir /b /a-d^|findstr /re ".*\....."') do echo(ren "%%~a" "%yyyymmdd%%VAR1%%%~xa"
for /f "delims=" %%a in ('dir /b /a-d^|findstr /re ".*\......"') do echo(ren "%%~a" "%yyyymmdd%%VAR2%%%~xa"
remove echo( to get it working.
If I understand you then this will rename the two files using preset variables for each one:
for %%a in ("%userprofile%\Desktop\test-dir\*") do (
if "%%~xa"==".12345" ren "%%a" "%variableA%-%variableB%%%~xa"
) else (
ren "%%a" "%variableC%-%variableD%%%~xa"
)
)

Resources