I have a folder with thousands of sub-folders, each containing one video file, and one subtitle file, like this:
Each of those text files (.srt) are subtitle files intended to display the filename (without extension) at the beginning and end of each video. For example, the contents of Track Two - Track Two.srt are:
1
00:00:00,500 --> 00:00:03,500
Track Two - Track Two
2
00:00:00,000 --> 00:00:00,000
Track Two - Track Two
Thanks to some serious StackHeads, I've been able to automate the creation of the text files by running the following batch script in the ./media/ parent directory:
for /R %%f in (*.flv *.mp4) do (
echo(1
echo(00:00:00,500 --^> 00:00:03,500
echo(%%~nf
echo(
echo(2
echo(00:00:00,000 --^> 00:00:00,000
echo(%%~nf
) > "%%~dpnf.srt"
Now all I have left to do is update the sixth line of each .srt file to make it show the filename for three seconds just prior to the end of the video. Ideally, the first numerical value would be 3.5 seconds prior to the end of the video, and the second value would be .5 seconds prior to the end.. and to make it even harder, it has to be in the Russian timecode .srt files use.
For example, if Track Two - Track Two is 01:36 long, the 6th line of Track Two - Track Two.srt should read:
00:01:32,500 --> 00:01:35,500
I can generate a text list of all of the video lengths, like this:
..and as long as I keep the folder names strictly numbered, they'll line up every time.
Is there any way to pull out the video lengths from the text file times.txt (assuming the order is perfect), and update the 6th line of each .srt file in Russian timecode format to make it display the title prior to the end the video file it references?
Any help is graciously appreciated!!
Also.. thanks again to dbenham, MC ND, payeli for your help before!! You're the best!
#ECHO OFF
SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /f "skip=1tokens=2,3,11delims=," %%a IN (list.csv) DO (
SET ttrack=%%a
SET videoname=%%~nb
set to_file="%%c\%%~nb.srt"
CALL :process
)
GOTO :EOF
:process
FOR /f "tokens=1-3delims=:" %%r IN ("%ttrack%") DO (
SET /a hr=10%%r
SET /a mi=1%%s
SET /a se=1%%t
)
CALL :subs 1
SET endtime=%hr:~-2%:%mi:~-2%:%se:~-2%,500
CALL :subs 3
SET starttime=%hr:~-2%:%mi:~-2%:%se:~-2%,500
echo(1
echo(00:00:00,500 --^> 00:00:03,500
echo(!videoname!
echo(
echo(2
echo(%starttime% --^> %endtime%
echo(!videoname!
ECHO(sent to %to_file%
GOTO :eof
::
:: subtract %1 seconds from hr,mi,se
::
:subs
SET /a se-=%1
IF %se% geq 100 GOTO :EOF
SET /a se+=60
SET /a mi-=1
IF %mi% geq 100 GOTO :EOF
SET /a mi+=60
SET /a hr-=1
GOTO :eof
Not hard.
All you'd need to do if this seems appropriate is to change
echo(1
...
echo(%videoname%
ECHO(sent to %to_file%
to
(
echo(1
...
echo(%videoname%
)>%to_file%
Related
I am working on a program using batch where the program read root directories from a text file and count total number of Folders and Files in all th give root directories. The program is working as it should be but I want to display the output in a certain way.
This is how I want to display output
0 : OF : 6
The first value should change each time program finish counting in one root directory. I have written code for it but the output I am getting is this.
Here is code I have written to change it.
:textUpdate
echo !counter! : OF : %number%
GOTO :EOF
where counter is the current number of root directory and number is total number of directories found in the text file. Is there any way to display the output like the first one.
you can abuse set /p to write to screen. It doens't append a line feed. You also need a Carriage Return to go back to the beginning of the line to overwrite the old output:
#echo off
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
for /l %%n in (1,1,6) do (
set /P "=Count %%n of 6!CR!" <nul
timeout 1 >nul
)
The first for /f loop is just to get a CR (Carriage Return). You have to use delayed expansion to be able to use it (%CR% does not work).
Inside a directory c:\configs I have files with various extensions including the extension .rac. I need a script for the Windows command prompt that looks inside c:\configs for the names of the files that end with the extension .rac, ignoring other extensions. Then of all the names that end with .rac extension the script must choose a random one and process it with the command c:\programs\submit.exe namerandom.rac.
For example, suppose that random .rac file is called mosaic.rac, then the script executes the command c:\programs\submit.exe mosaic.rac. Of course the mosaic.rac name changes each time the script is runs because it is a random selected from the all the .rac files found.
Anyone have an idea in how to do and that can put example code?
#echo off
setlocal EnableDelayedExpansion & set n=0
for /f "delims=" %%a in ('dir /b /A-D "*.rac"') do (
set "f=%%a" & set "f[!n!]=!f!" & set /a "n+=1")
set /a c=%random% %% n
echo !f[%c%]!
Explanation:
Line #4: it make a pseudo array in f with n incremented by 1
Line #5: it take a random number between 0 and the total count of files called n with the help of: %random% modulo n
In this way, this creates a number of variables automatically according to their position then %random% %% n picks one.
You might as well picks some manually like this:
echo !f[0]! !f[1]! !f[2]! !f[3]! !f[4]! !f[5]! ...
To accomplish that, you may use the following...
Firstly, to get all .rac files, use the dir command. The /B switch specifies to output only a bare file list without any headers nor footers. If you want to search the given directory recursively, add the /S switch:
dir /B "C:\configs\*.rac"
Secondly, you need to count the number of returned .rac files. You can use a for /F loop (parsing the output of dir /B) together with set /A for that:
set /A COUNT=0
for /F "delims=| eol=|" %%L in (
'dir /B "C:\configs\*.rac"'
) do (
set /A COUNT+=1
)
Thirdly, you need to compute a random number in the applicable range. The built-in variable RANDOM retrieves a random number from 0 to 32767, so we need a little maths. The result will be a number from 0 to %COUNT% - 1:
set /A RNDNUM=%RANDOM%%%COUNT
Fourthly, you can use another for /F loop with the skip option to select a random file (we skip the previously calculated number RNDNUM of lines).
The if statement ensures that no skip option is provided in case the random number is 0.
The goto command ensures that only the selected file is passed to submit.exe. If you omitted it, every file after the selection would be passed over to submit.exe too, one after another:
if %RNDNUM% gtr 0 (
set SKIP=skip=%RNDNUM%
) else (
set SKIP=
)
for /F "%SKIP% delims=| eol=|" %%L in (
'dir /B "C:\configs\*.rac"'
) do (
start "" /WAIT "submit.exe" "%%~L"
goto :CONTINUE
)
:CONTINUE
Put together those parts to get the final script.
Type each command and append /? in command prompt to get the respective help text displayed.
I would like to have a little batch file script which will work on Windows XP,7,8 and delete any occurrences of a specific file after a certain amount of time after the script is executed.
I have tried something similar:
forfiles -p "C:\what\ever" -s -m *somefile.pdf* /D -<number of days> /C "cmd /c del #path"
But this isn't what I'm actually looking for as it is deleting files older than a specific time. Any useful advice ?
There are basically three ways to solve this problem:
Keep the Batch file running all the time, delete the file after the desired time complete and restart the process. This is the method used in wOxxOm's answer.
Use Windows Task Scheduler to execute the "delete file" command every N days.
Place a Batch file in Startup folder so it run each time the user log in. The Batch file check if the file must be deleted to do it, calculate the date of the next time and store it in a companion data file. This is the method used in the Batch file below:
.
#echo off
setlocal EnableDelayedExpansion
rem Get today's date arranged as YYYYMMDD
rem (adjust lines below if MM/DD/YYYY is not the current locale date format)
for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
set "MM=%%a" & set "DD=%%b" & set "YYYY=%%c"
)
set "today=%YYYY%%MM%%DD%"
rem Read next date from companion file
set /P nextDate=< NextDate.txt
if %today% lss %nextDate% goto :EOF
rem Delete the file, calculate next date and store it in companion file
del "C:\what\ever\somefile.pdf"
set days=5
set mon=0
for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do (
set /A mon+=1
set "daysPerMonth[!mon!]=%%a"
)
set /A Ymod4=YYYY %% 4, MM=1%MM% - 100, DD=1%DD% - 100 + days
if %Ymod4% equ 0 set "daysPerMonth[2]=29"
if %DD% gtr !daysPerMonth[%MM%]! set /A DD-=daysPerMonth[%MM%], MM+=1
if %MM% gtr 12 set /A MM=1, YYYY+=1
if %MM% lss 10 set "MM=0%MM%"
if %DD% lss 10 set "DD=0%DD%"
echo %YYYY%%MM%%DD%> NextDate.txt
Note that you must manually create the NextDate.txt file with the first date, although additional code may be inserted in order to manage this initialization step.
Using only the built-in commands:
set days=5
for /L %%T in (1,1,%days%) do timeout 86400
del "C:\what\ever\*somefile.pdf*"
This will pause the execution of the batch file for the given number of days, then it'll delete the file(s).
I have 16 files that I would like to group together so that there are 3 files per folder (the remainder would be placed in a separate folder). Essentially the files have a date string that I would like to use to group the files. For example, 201301 is January 2013. Is there a way to create a batch program or otherwise to do something like the following:
1) Create list of all strings of the same form as 201301. This can be done by choosing a starting point (in this case 11 characters into the title) to start counting from and then count to 5.
Would something like this fit the bill?
2) Sort these strings from smallest to largest using something like:
:startSort // Set our upper "array bound"
set /a total=count-1
:RestartSort // Restart the sort from the beginning
set /a count=1
:sortLoop
set /a next=%count%+1 // Swap n and n+1
call :swap %count% %next%
set /a count=count+1
if "%swapped%" == "true" goto :RestartSort // If the variables were swapped,
// start again
if "%count%" == "%total%" goto :output // If we're done,
// output the results
goto :sortLoop // Back to the start to
// swap the next two
3) Count to three and then create a folder in which to store the three files
4) store the three files
5) continue until no more files remain
The only issue I have with this setup is that it will probably not know what to do when it gets to the last file that has no other files to be grouped with. Is there a way to get it to account for this - some way it knows it's hit the end of the list?
For reference, the file names are of the form 12345_ABCDE_20130101_20130101, and the folder names would simply be something like 201301-201303 (to use the same example values).
code example:
#ECHO OFF &SETLOCAL disableDelayedExpansion
SET /a Counter=0
SET /a FilesPerFolder=3
FOR /f "delims=" %%a IN ('DIR /b /a-d /on "%cd%\test\*"') DO (
SET /a Test=Counter%%FilesPerFolder
SET /a TargetFolder=Counter/FilesPerFolder
SETLOCAL enableDelayedExpansion
MD "%cd%\test\Folder!TargetFolder!" 2>nul
MOVE "%cd%\test\%%~a" "%cd%\test\Folder!TargetFolder!" >nul
ENDLOCAL
SET /a Counter+=1
)
After fiddling around for the first time with the command-line and ImageMagic, I have been able to do the following:
c:\test\paper.pdf contains a pdf file
c:\test>convert paper.pdf output-%d.tiff
The pdf file contains five pages, and the output is as expected 5 tiff files :-) Now I want to put multiple files in c:\test and loop through them, creating pages based on the original filename. So assume the following files in c:\test:
paper.pdf (5 pages)
example.pdf (2 pages)
new.pdf (1 page)
The output of a batch script should be 8 tiff files in the c:\test\tiffs\ folder:
paper-0.tiff paper-1.tiff paper-2.tiff paper-3.tiff paper-4.tiff
example-0.tiff example-1.tiff
new-0.tiff
and I would very much like the command line return the time it took converting the pdf's to tiffs:
c:\test>convert.bat
c:\test>This action took 120 seconds
I'm trying to write this batch file but since it's my first try I'm having trouble. I am first trying to loop through the test folder and create all the tiffs (leaving timing the process for now):
for %%f in (C:\test\) do convert %%f.pdf %%f-%%d.tiff
I would have expected this to work but got an error:
C:\Users\Me>convert c:\test\c:\test\.pdf c:\test\c:\test\-%d.tiff convert.exe:
unable to open image `c:\test\c:\test\.pdf': Invalid argument #
error/blob.c/OpenBlob/2646. convert.exe: no decode delegate for this image
format `c:\test\c:\test\.pdf' # error/constitute.c/ReadImage/552. convert.exe:
no images defined `c:\test\c:\test\-%d.tiff' #
error/convert.c/ConvertImageCommand/3106.
What am I doing wrong?
Timing
This is one of those jobs that it is just wrong to do (for real—it's OK to do it to show off) with batch/CMD. Nearly every programming language I've ever encountered would be better at doing this than CMD.
This particular (hackish) implementation will not work if the elapsed time goes past midnight of any given day, and depending on how you have dates configured in your locale, it might break if the run starts before 1 P.M. and finishes after 1 P.M.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=5 delims= " %%t IN ('^<NUL time') DO SET START_TIME=%%t
:: Stuff that you're timing.
FOR /F "tokens=5 delims= " %%t IN ('^<NUL time') DO SET END_TIME=%%t
SET ELAPSED=
FOR /F "delims=:. tokens=1,2,3,4" %%a IN ("%START_TIME%") DO (
FOR /F "delims=:. tokens=1,2,3,4" %%n IN ("%END_TIME%") DO (
SET /A HOURS=%%n-%%a
SET /A MINUTES=%%o-%%b
SET /A SECONDS=%%p-%%c
SET /A HUND=%%q-%%d
SET /A TOTAL=!HOURS!*3600 + !MINUTES!*60 + !SECONDS!
IF !HUND! LSS 0 (
SET /A TOTAL=!TOTAL!-1
SET /A HUND=!HUND!+100
)
IF !HUND! LSS 10 SET HUND=0!HUND!
SET ELAPSED=!TOTAL!.!HUND!
)
)
#ECHO.
#ECHO.
#ECHO This action took %ELAPSED% seconds.
ImageMagick
The problem I see with your convert command is that you've not told CMD what pattern to search for. It sounds like you want *.pdf. Doing this will mean that you don't need to append ".pdf" to the end of the input file name and need to remove the extension when specifying the output file name. The %%~dpnf produces the entire path to the file without the extension.
FOR %%f IN (C:\temp\*.pdf) do convert "%%~f" "%%~dpnf-%%d.tiff"
EDIT: To put the PDF's in a different location, change the %%f substitution:
FOR %%f IN (C:\temp\*.pdf) do convert "%%~f" "\path\to\tiffs\%%~nf-%%d.tiff"
Better Method?
I guess I should at least put in a plug for doing it the Rightâ„¢ way. If you didn't want to invoke your command from a script in a language that supported timing (like Python), you could just retrieve the system time as an integer. This strategy will work until roughly 2038. I used Perl in this example.
#ECHO OFF
FOR /F %%t IN ('perl -e "print(time());"') DO SET START_TIME=%%t
:: stuff to time
FOR /F %%t IN ('perl -e "print(time());"') DO SET END_TIME=%%t
SET /A ELAPSED=%END_TIME%-%START_TIME%
#ECHO This step took %ELAPSED% seconds.