Current code:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
:: Create Empty Folder
rd /Q "%Temp%\Temp" 2>nul & mkdir "%Temp%\Temp"
:: Loop through Folders
pushd "xPath=c:\processing"
for /d %%D in (*) do call :Process "%%~fD"
popd
goto End
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Process <Parent>
:: Folder Name
set "xFolder=%~nx1"
:: Set Sub Folder
if not exist "%~1\VIDEO\" goto :eof
pushd "%~1\VIDEO"
:: Loop through Videos
for /f "delims=" %%A in ('dir *.avi /b') do if exist "%%~fA" (
set "xDateWritten=%%~tA"
set "xDateGMT=0000/00/00 00:00:00"
for /f "tokens=1,2" %%X in ('robocopy . "%Temp%\Temp" "%%~nxA" /TS /FP /NS /NC /NP /NJH /NJS /NDL /L') do set "xDateGMT=%%X %%Y"
rem Format = FF-FF-YYYYMMDD-HHhMMmSSs-FF-FF.ext
set "xFrame=00,00000"
for /f %%X in ('exiftool -p "$Framerate,$Framecount" "%%~fA"') do set "xFrame=%%~X"
set "xSize=%%~zA"
set "xName=%xFolder:~0,2%-%xFolder:~2,2%-!xDateWritten:~6,4!!xDateWritten:~0,2!!xDateWritten:~3,2!-!xDateWritten:~11,2!h-!xDateWritten:~14,2!m-!xDateGMT:~17,2!s-%xFolder:~4,2%-%xFolder:~6,2%%%~xA"
echo !xName!
ren "%%~fA" "!xName!"
echo !xName!,!xSize!,!xFrame!>>C:\processing\RenameOutput.csv
)
popd
goto :eof
:End
endlocal
pause
I previously believed my folder structure would be ex:
C:\processing\15010107\Video\files.avi
, but it's actually
C:\processing\15010107\Video\filedate\files.avi
, so I need it to search 1 more subfolder down than it was before.
Also, the renamed files need to have 24hr format for the time, it's currently outputting the pm time but without a pm flag, which can get mixed up with the am files.
I believe that these changes should cover your new issues.
Changed the Folder Loop to also Loop through the sub filedate folders.
The Process function now takes two parameters the parent folder and current folder.
The Hour is now adjusted to 24 hour format.
Full Script (Added Comments)
#echo off
setlocal EnableExtensions EnableDelayedExpansion
:: Create Empty Folder
rd /Q "%Temp%\Temp" 2>nul & mkdir "%Temp%\Temp"
:: Loop through Folders
pushd "xPath=c:\processing"
for /d %%D in (*) do if exist "%%~fD\VIDEO\" (
pushd "%%~fD\VIDEO\"
for /d %%S in (*) do call :Process "%%~fD" "%%~fS"
popd
)
popd
goto End
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Process <Parent> <Working>
:: Folder Name
set "xFolder=%~nx1"
:: Set Working Directory
if not exist "%~f2" goto :eof
pushd "%~f2"
:: Loop through Videos
for /f "delims=" %%A in ('dir *.avi /b') do if exist "%%~fA" (
rem Retrieve the file time stamp
set "xDateWritten=%%~tA"
rem Retrieve the Seconds using RoboCopy
set "xDateGMT=0000/00/00 00:00:00"
for /f "tokens=1,2" %%X in ('robocopy . "%Temp%\Temp" "%%~nxA" /TS /FP /NS /NC /NP /NJH /NJS /NDL /L') do set "xDateGMT=%%X %%Y"
rem Retrieve the Video frame information
set "xFrame=00,00000"
for /f %%X in ('exiftool -p "$Framerate,$Framecount" "%%~fA"') do set "xFrame=%%~X"
rem Retrieve the file size
set "xSize=%%~zA"
rem Adjust to 24 hours
set "xHour=!xDateWritten:~11,2!"
if "!xDateWritten:~17,2!"=="PM" set /a "xHour+=12"
rem Format = FF-FF-YYYYMMDD-HHh-MMm-SSs-FF-FF.ext
set "xName=%xFolder:~0,2%-%xFolder:~2,2%-!xDateWritten:~6,4!!xDateWritten:~0,2!!xDateWritten:~3,2!-!xHour!h-!xDateWritten:~14,2!m-!xDateGMT:~17,2!s-%xFolder:~4,2%-%xFolder:~6,2%%%~xA"
rem Display, Rename, and Save
echo !xName!
ren "%%~fA" "!xName!"
echo !xName!,!xSize!,!xFrame!>>C:\processing\RenameOutput.csv
)
popd
goto :eof
:End
endlocal
pause
Related
I am trying to create a folder by date time in my batch file using following code
#echo off & for /F "tokens=1-4 delims=/ " %%A in ('date/t') do (
set DateDay=%%A
set DateMonth=%%B
set Date=%%C
set DateYear=%%D
)
#echo off & for /F "tokens=1-4 delims=/ " %%D in ('time/t') do (
set DateTime=%%D
)
set CurrentDate=%Date%-%DateMonth%-%DateYear%-0%time:~0,2%.%time:~3,2%.%time:~6,2%
mkdir %CurrentDate%
using this I get folder name as 22-02-2021-010.01.37
But if time Hours is in 1 to 9 hr my folder is displayed as
22-02-2021-0 9.59.19 there is always a space in 0 and 9 and 1 to 9 hr is not displayed as 01,02,03 Hr
Answer Should Be:
22-02-2021-009.59.19
The best and the correct method to get this is to use the date independently of the region day/month order, you can use "WMIC os GET LocalDateTime" as a source, since it's in ISO order:
#echo off
Title Get FileName With Date and Time
Call :GetFileNameWithDateTime MyCurrentDate
echo %MyCurrentDate%
MkDir %MyCurrentDate%
pause & exit
::----------------------------------------------------------------------------------
:GetFileNameWithDateTime <FileName>
for /f "skip=1" %%x in ('wmic os get localdatetime') do if not defined MyDate set "MyDate=%%x"
set "%1=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%-%MyDate:~8,2%-%MyDate:~10,2%"
Exit /B
::----------------------------------------------------------------------------------
set "CurrentDate=%Date%-%DateMonth%-%DateYear%-0%time:~0,2%.%time:~3,2%.%time:~6,2%"
set "CurrentDate=%currentDate: =0%"
mkdir %CurrentDate%
substituting 0 for in currentdate
Tips : Use set "var1=data" for setting values - this avoids problems caused by trailing spaces. In comparisons, use if "thing1" == "thing2" ... to avoid problems caused by spaces in thing1/2.
If you want something which will work on any modern system, and still output the directory name in your specific format/order, regardless of user or locale settings, then…
you could do it like this from a batch-file:
#For /F "Tokens=1-6 Delims=/: " %%G In ('%SystemRoot%\System32\Robocopy.exe \: . /NJH /L ^| %SystemRoot%\System32\find.exe " 123"') Do #MD "%%I-%%H-%%G-0%%J.%%K.%%L"
or directly from the Windows command-line, cmd.exe:
For /F "Tokens=1-6 Delims=/: " %G In ('%SystemRoot%\System32\Robocopy.exe \: . /NJH /L ^| %SystemRoot%\System32\find.exe " 123"') Do #MD %I-%H-%G-0%J.%K.%L
I would like a command in a batch file to only execute if it has not been ran for the last 15 minutes. To achieve this I can create a "last_run" file to log the time last ran.
Where I am stuck is comparing the time last modified to the current time and taking action if the time last modified.
Here is my current code:
#echo off
set filename=last_run.txt
if not exist %filename% (
rem NOT EXISTS, CREATE FILE THEN PRINT THE LIST
echo.>"%filename%"
GOTO PrintList
) else (
rem FILE EXISTS, GET TIME LAST MODIFIED
FOR %%? IN (%filename%) DO (set filetime=%%~t?)
echo %filetime%
rem IF TIME LAST MODIFIED > 15 MINS PRINT THE LIST
if timediff??(%filetime%, current) > 15 mins {
GOTO PrintList
} else {
GOTO End
}
)
:PrintList
rem PRINT THE LIST
echo now print the list
rem WRITE TO THE FILE TO UPDATE TIME LAST MODIFIED
echo.>"%filename%"
GOTO End
:End
Another implementation using powershell from your batch-file:
#Echo Off
Set "filename=last_run.txt"
Set "minutes=15"
If Not Exist "%filename%" GoTo :PrintList
"%__APPDIR__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile If(((Get-Date)-(Get-Item ".\%filename%").LastWriteTime).Minutes -LT %minutes%){Exit 1}
If ErrorLevel 1 Exit /B
Rem Your payload below here.
:PrintList
CD.>"%filename%"
If you are happy to accept that the PC running this code will always have the appropriate entries in %PATH% and %PATHEXT%, you can change "%__APPDIR__%WindowsPowerShell\v1.0\powershell.exe" to just PowerShell.
Besides the missing time calculation, your code has a delayed expansion problem. (My solution below doesn't need delayed expansion)
cmd is incredibly crude when it comes to date/time calculation (it can be done, but...).
Better use the help of another language (like PowerShell):
#echo off
setlocal
set "filename=last_run.txt"
set "minutes=15"
if not exist "%filename%" (
break>"%filename%"
goto :PrintList
)
for /f %%a in ('"powershell Test-Path %filename% -OlderThan (Get-Date).AddMinutes(-%minutes%)"') do set "older=%%a"
if "%older%" == "True" (
echo %filename% is older than %minutes% minutes; print list
break>"%filename%"
goto :PrintList
) else (
echo %filename% is younger than %minutes% minutes; exiting
goto :eof
)
:PrintList
echo insert your payload here.
You could use total minutes with a powerhell command.
#echo off
set error=0
if not exist last_run.txt echo File not yet existed, first run will be now & set /a error+=1
for /f "delims=," %%i in ('powershell -command "(New-TimeSpan -Start (Get-Date "01/01/1970") -End (Get-Date)).TotalMinutes"') do set "now=%%i"
if "%error%" == "1" goto :run
for /f %%a in (last_run.txt) do set earlier=%%a
set /a result=%now%-%earlier%
if %result% geq 15 (
:run
echo RUN COMMANDS HERE
echo %now%>tmp.tmp
)
The concept is simple. We get the epoch time in minutes. Store the value in a file. Then compare the current minutes with the minutes in the file. if %now% is equal to or more than 15 from %earlier% the command will run. Additionally, if the file does not yet exist, it will create it and run the command first time. From there it will only run if the seconds in the file is 15 or less than current minutes.
With batch variable/parameter expansion like %~t1 one can get a timestamp of a file.
I would like to set the year of the file to another variable would like to support multiple locales.
How can you get a file's datetime, independent of locale and regional settings? No powershell please.
I'll post few options
1)First one is with wmic (not available for XP home edition) (LastModified can be changed with CreationDate or LastAccessed )
#echo off
set file_loc=.\temp_file
for %%# in ("%file_loc%") do set file_loc=%%~dpfnx#
set file_loc=%file_loc:\=\\%
for /f "delims=." %%t in ('"WMIC DATAFILE WHERE name="%file_loc%" get LastModified /format:value"') do (
for /f %%$ in ("%%t") do if "%%$" neq "" set %%$
)
echo %LastModified%
echo year : %LastModified:~0,4%
echo month : %LastModified:~4,2%
echo day : %LastModified:~6,2%
2). Jscript/.bat hybrid (DateLastModified can be changed to DateCreated or DateLastAccessed .Time format can be changed to whatever you want ):
#if (#X)==(#Y) #end /****** jscript comment ******
#echo off
set file_loc=.\temp_file
for %%# in ("%file_loc%") do set file_loc=%%~dpfnx#
::set file_loc=%file_loc:\=\\%
cscript //E:JScript //nologo "%~f0" "%file_loc%"
exit /b 0
****** end of jscript comment ******/
var file_loc = WScript.Arguments.Item(0);
var fso = new ActiveXObject("Scripting.FileSystemObject");
var the_file=fso.GetFile(file_loc);
var the_date= new Date(the_file.DateLastModified);
WScript.Echo(the_date.getFullYear());
WScript.Echo(the_date.getMonth());
WScript.Echo(the_date.getUTCDate());
3) selfcompiled jscript.net/bat hybrid (GetLastWriteTime can be changed to GetLastAccessTime or GetCreationTime . Time format can be changed) :
#if (#X)==(#Y) #end /****** silent line that start jscript comment ******
#echo off
::::::::::::::::::::::::::::::::::::
::: compile the script ::::
::::::::::::::::::::::::::::::::::::
setlocal
if exist "%~n0.exe" goto :skip_compilation
set "frm=%SystemRoot%\Microsoft.NET\Framework\"
:: searching the latest installed .net framework
for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
if exist "%%v\jsc.exe" (
rem :: the javascript.net compiler
set "jsc=%%~dpsnfxv\jsc.exe"
goto :break_loop
)
)
echo jsc.exe not found && exit /b 0
:break_loop
call %jsc% /nologo /out:"%~n0.exe" "%~dpsfnx0"
::::::::::::::::::::::::::::::::::::
::: end of compilation ::::
::::::::::::::::::::::::::::::::::::
:skip_compilation
set file_loc=.\temp_file
for %%# in ("%file_loc%") do set file_loc=%%~dpfnx#
"%~n0.exe" "%file_loc%"
exit /b 0
****** end of jscript comment ******/
import System;
import System.IO;
var arguments:String[] = Environment.GetCommandLineArgs();
var the_file=arguments[1];
var last_modified=File.GetLastWriteTime(the_file);
Console.WriteLine(last_modified.ToString("yyyy-MM-dd"));
4). robocopy - with this you can get only last modified date (with other methods you can get all time attributes).As time stamps in robocopy are always YYYY/MM/DD HH:mm:SS this can be used...
#ECHO OFF
set file_loc=.\temp_file
for %%# in ("%file_loc%") do set file_dir=%%~dp#
for %%# in ("%file_loc%") do set file_name=%%~nx#
pushd %file_dir%
for /f "tokens=1,2" %%a in ('robocopy "." "%temp%" /l /fat /ts /LEV:1 /NP /NC /NS /NJS /NJH^|findstr /i /e /c:"%file_name%"') do (
echo %%a %%b
)
popd
EDIT Here are ready to use parametrized scripts using all the listed methods:
fileModifiedTime.bat - gets last modified time of file with settings independent format.Based on robocopy
fileTimes.bat - gets file time stamps with WMIC
dirTimes.bat - gets directory time stamps with WMIC
fileTimesJS.bat - file time stamps with jscript
dirTimesJS.bat - directory time stamps with jscript
fileTimesNET.bat - file time stamps with .NET
dirTimesNET.bat - dir time stamps with .NET
I need a command to use in a batch file, which copies the contents of a remote directory to a local directory over http.
For example to copy folder http ://path//folder to C:\folder
I need to do this without installing any additional tools.
Thanks in advance!
There's no standard way for an http server to list accessible directories.
For example I took http://unomoralez.com/content/files/catalog2/source/ as one of the common ways to list directory with http. Your site could look different though but there's no way for me tho know... (ther's a temp list2.txt file - you can remark its deletion to check the format of directory page and tell me if its not working. IF it is IIS could look like this: http://live.sysinternals.com/tools/)
the script downloads all content into .\download_dir (not recursive download) :
#if (#X)==(#Y) #end /****** jscript comment ******
#echo off
::::::::::::::::::::::::::::::::::::
::: compile the script ::::
::::::::::::::::::::::::::::::::::::
setlocal
if exist simpledownloader.exe goto :skip_compilation
set "frm=%SystemRoot%\Microsoft.NET\Framework\"
:: searching the latest installed .net framework
for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
if exist "%%v\jsc.exe" (
rem :: the javascript.net compiler
set "jsc=%%~dpsnfxv\jsc.exe"
goto :break_loop
)
)
echo jsc.exe not found && exit /b 0
:break_loop
call %jsc% /nologo /out:"simpledownloader.exe" "%~dpsfnx0"
::::::::::::::::::::::::::::::::::::
::: end of compilation ::::
::::::::::::::::::::::::::::::::::::
:skip_compilation
:: download the file
:::::::::::::::::::::::::::::::::::::::::
::::just change the link and the file::::
:::::::::::::::::::::::::::::::::::::::::
::!!!!!!!!!!!!!!!!!!!!!!!!!:::
simpledownloader.exe "http://unomoralez.com/content/files/catalog2/source/" "list2.txt"
md download_dir >nul 2>&1
for /f "skip=1 tokens=4 delims=>< " %%a in ('type list2.txt^| find /i "href" ') do (
simpledownloader.exe "http://unomoralez.com/content/files/catalog2/source/%%a" .\download_dir\%%a
)
del /q /f list2.txt
exit /b 0
****** end of jscript comment ******/
import System;
var arguments:String[] = Environment.GetCommandLineArgs();
var webClient:System.Net.WebClient = new System.Net.WebClient();
print("Downloading " + arguments[1] + " to " + arguments[2]);
try {
webClient.DownloadFile(arguments[1], arguments[2]);
} catch (e) {
Console.BackgroundColor = ConsoleColor.Green;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("\n\nProblem with downloading " + arguments[1] + " to " + arguments[2] + "Check if the internet address is valid");
Console.ResetColor();
Environment.Exit(5);
}
As you have powershell you also have .net so this code will be executed without problems for you.
This was more or less a code that I already had but you can also check this -> https://code.google.com/p/curlie/ if you are familiar with cURL and create a hybrid jscript/.bat file.
I have a small Win7 dos batch and I am wondering how to do it right. Here what I do:
#echo OFF
#FOR %%D IN (*.sqlite) DO (
sqlite3 %%D "pragma integrity_check;" > %%D.check
type %%D.check
set /p CHECK= < %%D.check
del %%D.check
echo "%CHECK%"
)
I would expect that CHECK is set to the result of sqlite output. Though "type" shows the expected result, CHECK is empty!
And I do not understand what I am doing wrong.
I also tried it without using a tmpfile
FOR /F "tokens=*" %%i in ('sqlite3 %%D "pragma integrity_check;"') do SET CHECK=%%i
but this also does not work...
I'd appreciate any help/hint.
Tnx in advance,
Robert
Check is set to the correct value, but you can't see it with echo %check%, as this line is expanded while parsing the complete FOR-block, not at the execution time.
You can change to delayed expansion or a simple call :subroutine.
#echo OFF
setlocal EnableDelayedExpansion
FOR %%D IN (*.sqlite) DO (
sqlite3 %%D "pragma integrity_check;" > %%D.check
type %%D.check
set /p CHECK= < %%D.check
del %%D.check
echo "!CHECK!"
)
or
#echo OFF
FOR %%D IN (*.sqlite) DO (
sqlite3 %%D "pragma integrity_check;" > %%D.check
type %%D.check
set /p CHECK= < %%D.check
del %%D.check
call :output
)
exit /b
:output
echo "%CHECK%"
exit /b
if %%D.check contain not only one line
then the set /p=will...?