I want to create one bat file that will move files from one location to one backup folder. Condition is I need to move all folders which are older than 30 days inside parent directory. Name of folder is creation date of folder.
For example:
All files of 17 October 2012 would be there inside folder named 10172012.Source folders are:
C:\Data\DataIn\Processed\10172012
C:\Data\DataIn\Processed\09172012
C:\Data\DataIn\Processed\08172012
So on today bat file should move folders "09172012", "08172012" to destination backup folder:
D:\Backup\Processed\
#echo off
setlocal EnableDelayedExpansion
rem Get Julian Day number of today's date
for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
set /A m=1%%a %% 100, d=1%%b %% 100, y=%%c
)
set /A A=(m-14)/12, todayJDN = (1461*(y+4800+A))/4 + (367*(m-2-12*A))/12 - (3*((y+4900+A)/100))/4 + d - 32075
rem Process all folders
for /D %%a in (*) do (
rem Get Julian Day Number of this folder
set folder=%%a
set /A m=1!folder:~0,2! %% 100, d=1!folder:~2,2! %% 100, y=!folder:~4!
set /A "A=(m-14)/12, folderJDN = (1461*(y+4800+A))/4 + (367*(m-2-12*A))/12 - (3*((y+4900+A)/100))/4 + d - 32075"
rem Move folder if it is older than 30 days
set /A daysOlder=todayJDN - folderJDN
if !daysOlder! gtr 30 move %%a D:\Backup\Processed\
)
Julian Day Numbers are described here: http://www.hermetic.ch/cal_stud/jdn.htm
Using shell scripting it was easier to do. Finally I implemented this using shell scripting.
Related
I am working with a video camera and we have a program that displays the saved videos from an SD card when inserted into a PC. At some point the manufacturer of the camera changed the directory structure and naming convention for the saved files. I would like to create a batch file or VBS Script that will reorganize the files into the old structure. This will be a quick and dirty fix for windows based PC's and until we can re-write the software which will include support for MAC's. It can be a batch file or a VBS Script but must run under a Windows command prompt with no additional software installed. The camera has front and rear cameras so there are 2 files to deal with and there could be 1 or more video captures to relocate.
The number of folders would depend on the number of videos saved, let's say there are 4 videos saved so the original structure looked like this.
- video1
- video.TS
- video2.TS
- video2
- video.TS
- video2.TS
- video3
- video.TS
- video2.TS
- video4
- video.TS
- video2.TS
The new structure looks like this
- Normal
- F
- DATETIME-000001F.TS
- DATETIME-000002F.TS
- DATETIME-000003F.TS
- DATETIME-000004F.TS
- R
- DATETIME-000001R.TS
- DATETIME-000002R.TS
- DATETIME-000003R.TS
- DATETIME-000004R.TS
The object is to move these files into the older file structure so the software can read and display them. I already have a batch file that runs when the SD card is inserted so my assumption is that I can include some script before the normal process fires to move these files around. I am pretty rusty with scripting and need some guidance.
My current script look like this.
setlocal enableextensions enabledelayedexpansion
set count=0
for %%x in (\Normal\F\*.TS) do (
set /a count += 1
mkdir video!count!
move /Y \Normal\F\*.TS \video!count!\video.TS
move /Y \Normal\R\*.TS \video!count!\video2.TS
)
endlocal
There are always 2 videos, 1 for the front camera and 1 for the rear camera so I am only using the "F" directory to get the count.
Without the move commands it creates the directory structure just fine... If there is 1 file it only creates 1 folder, if there are 8 files it creates 8 folders. but when there are multiple files it wants to put all of the files in the first folder.
I assume I would need to nest another loop but everything I have tried has failed and this is the closest attempt.
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the source directory, destination directory, target directory,
rem batch directory, filenames, output filename and temporary filename [if shown] are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\normal\F\*-*.ts" '
) DO (
SET "video2=%%~na"
SET "video2=!video2:~0,-1!R%%~xa"
FOR /f "tokens=2delims=.-" %%i IN ("%%a") DO (
SET "video=%%i"
SET /a video=1!video:~0,-1!-1000000
MD "%destdir%\video!video!" 2>NUL
MOVE /y "%sourcedir%\normal\F\%%a" "%destdir%\video!video!\video.TS" >NUL 2>nul
MOVE /y "%sourcedir%\normal\R\!video2!" "%destdir%\video!video!\video2.TS" >NUL 2>nul
)
)
)
GOTO :EOF
You would need to change the values assigned to sourcedir and destdir to suit your circumstances. The listing uses a setting that suits my system.
I deliberately include spaces in names to ensure that the spaces are processed correctly.
First, assign to %%a each filename found in the ...\F directory.
Then construct the corresponding filename in ...\R by taking the name part of %%a, removing the last character and replacing it with R, then appending the extension from %%a.
Next, derive the sequence number from %%a by selecting the second token from %%a using - and . as delimiters. Set the number part of the destination directoryname by prefixing all bar the last character of video with 1 and subtracting 1000000 to convert it to the natural form.
Create the destination directory and move in and rename the source files
[edit in response to comments]
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "drives=d e f g h i j k l m n o p q r s t u v w x y z"
SET "sourcedir=normal"
:: locate drive that has directory "?:\normal\f"
FOR %%d IN (%drives%) DO IF EXIST "%%d:\%sourcedir%\f\." SET "sourcedir=%%d:\%sourcedir%"&SET "destdir=%%d:\video"&GOTO founddrive
ECHO Could not find "%sourcedir%\f" on any drive
GOTO :eof
:founddrive
SET /a destnum=1
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\f\*-*.ts" '
) DO (
MD "%destdir%!destnum!" 2>NUL
SET "filename=%%~na"
set "filename=!filename:~0,-1!R%%~xa"
MOVE /y "%sourcedir%\F\%%a" "%destdir%!destnum!\video.TS" >NUL 2>nul
MOVE /y "%sourcedir%\R\!filename!" "%destdir%!destnum!\video2.TS" >NUL 2>nul
SET /a destnum+=1
)
GOTO :EOF
OK, so this version first scans for the directoryname, then picks the files and places them, with namechanges, in directory video1... on the same drive.
Suppose I have 50 files sorted by name.. I would like to create a batch script which gives me the following result:
Files 1 through 5 -> 01-05
Files 6 through 10 -> 06-10
and so on..How can I create a batch script to achieve this?
Note that 01-05 and 06-10 are directory names..
EDIT: Details
For eg. Consider this:
Source Directory:
101.mp4
102.mp4
103.mp4
104.mp4
and so on..
I want a resulting directory structure like this:
Destination Directory:
101-105:
101.mp4
102.mp4
103.mp4
104.mp4
105.mp4
106-110:
106.mp4
107.mp4
108.mp4
109.mp4
110.mp4
and so on..
This is what you want, change fileCount to change the file number in each subdirectory:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set fileCount=5
set filesNow=0
set nameStart=000
set nameEnd=000
FOR /F "usebackq delims=" %%i IN (`dir /b /O:N *.mp4`) do (
set /a filesNow+=1
set /a tmpValue=filesNow %% fileCount
::echo !filesNow!
::echo !fileCount!
::echo %%i
::echo !tmpValue!
if "!tmpValue!"=="1" (
set "nameStart=%%~ni"
mkdir _tmpDir_
)
move %%~nxi _tmpDir_\
if "!tmpValue!"=="0" (
rename _tmpDir_ !nameStart!-%%~ni
)
set "nameEnd=%%~ni"
)
if exist _tmpDir_ rename _tmpDir_ %nameStart%-%nameEnd%
You need to put them inside a bat/cmd file to work.
filesNow is for file number count.
Basically it's create a tmp folder and move files inside,
When files inside it reach the number, change the folder's name.
Several testing echo command I didn't remove, just used :: to comment them out, you can remove the :: to test them again.
got this piece of code:
forfiles /P %ParentFolder% /S /M %Format% /C "cmd /c %exeFile% #path"
executing some exe for every file matching format as parameter.
any way to add "creation date" as a condition to run command via CMD?
something like :
for all files in directory (recursive) X if creation date newer then 1 day ago do (run) some exe with this file's path as param
This is not possible with forfiles, because, when the /D option is provided, it only regards the last modification date only (not even the modification time).
Unfortunately, there are no native commands for date/time maths, so I suggest to switch to a language that is capable of that; for instance, PowerShell, VBScript, JavaScript (which are all native to Windows past XP).
In case the modification date could be used, and a simple check with the date of today is sufficient, the following forfiles command line could be used:
forfiles /S /P "%ParentFolder%" /M "%Format%" /D +0 /C "cmd /C \"%exeFile%\" #path"
The /D option with a non-negative number lets forfiles return files that have been modified the given number of days after today or later (although you would need a time-machine; hence I consider this a design flaw). For +0 as the given number of days, all matching files modified today are returned, because forfiles /D only checks the modification date but does not care about the modification time.
If a simple equality check of the creation date with the date of today is fine for you, it can be done in batch-file scripting quite easily though (see all the explanatory rem remarks for how the following script works):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "ParentFolder=."
set "Format=*.*"
set "exeFile=" & rem // (full path to executable file)
set "tmpFile=%TEMP%\%~n0_%RANDOM%.tmp"
rem // Create a temporary file and retrieve its creation date:
2> nul del "%tmpFile%" & > "%tmpFile%" break & set "TODAY="
for /F "skip=5" %%J in ('dir /N /4 /-C /T:C "%tmpFile%"') do (
if not defined TODAY set "TODAY=%%J" & del "%tmpFile%"
)
rem // Change to predefined parent directory:
pushd "%ParentFolder%" && (
rem // Return all files recursively:
for /F "delims=" %%I in ('dir /B /S /A:-D "%Format%"') do (
rem // Determine the creation date for the current file:
set "FIRST=#"
for /F "skip=5" %%J in ('dir /N /-C /T:C "%%I"') do (
rem // Regard line listing file only, ignore summary lines:
if defined FIRST (
set "FIRST="
rem // Check creation date against today:
if "%%J"=="%TODAY%" (
rem // Return files created today:
echo "%%I" has been created today.
rem // Run external program on found file:
if defined exeFile "%exeFile%" "%%I"
)
)
)
)
rem // Restore previous working directory:
popd
)
endlocal
exit /B
I am using two dir command lines here:
the first one returns a bare list of files recursively (/S; no directories because of /A:-D) without any dates/times, headers and footers, due to switch /B; not using this switch would lead to header and footer lines for the whole output and for every iterated sub-directory also, so the output would be quite complicated to be parsed;
the second one receives each file returned by the first one; since there is no /B but the /N option, the file creation date/time is returned (/T:C); for every file the output looks like this:
Volume in drive D is DATA
Volume Serial Number is 0000-0000
Directory of D:\Data
2016/09/29 16:00 1024 current_file.txt
1 File(s) 1024 bytes
0 Dir(s) 1099511623680 bytes free
the first token of the sixth line constituting the creation date is split off and compared against the current date %DATE%; to ignore the header, the skip=5 option of the for /F loop is used; to ignore the summary lines, the variable FIRST is used;
Note that the date format is locale-dependent; as long as there appear no spaces in the date, this is no problem as the current date is also determined by the dir command applied on a temporary file.
Looking at the forfiles /? shows the switch /D that will exclude files that are younger (/d -<days>) or older (/d +<days>) than the given value for <days>.
As you want the files from today, you would set <date> to 0.
Notice, that this will look on the changed date!
Other way would be to use a for /r-loop and get a list of the creation date with dir /T:C ; to sort it add /O-D. Then separate that using a for /f loop to get the lines of the output of dir and another one to separate it (possibly easier without the nested loops).
You can than compare the creation date with %date% or when using one day=24 hrs compare the creation time with %time% additionally.
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 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%