"set /p myvar= < file.txt" does not work - why? - sqlite

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...?

Related

cmd batch file check if current hour is equal to one of specific hour

I would like to develop a batch file to check the current time hour is equal to specific hour.
As long as n+2 hour (e.g. 0, 2, 4, 6, 8, 10, etc...) is matched with system current hour, it will echo to valid message, otherwise it will echo to invalid message.
Anyone can help me? Thanks.
Source Code
FOR /F %%a IN ('Powershell -Nop -c "Get-Date -Format 'HH'"') DO SET getcurrHour=%%a
FOR /L %%a IN (0,2,22) DO SET hourList=%%a
IF %getcurrHour% == %hourList% (
ECHO It's valid.
) ELSE (
ECHO It's not valid.
)
If you're using PowerShell anyhow, then let it do more of the work for you.
#%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile^
"$Hr = (Get-Date).Hour;"^
"If (((($Hr / 2) - [Math]::Truncate($Hr / 2)) * 10) -Eq 5)"^
"{ Write-Host \"It's not valid.\" }"^
"Else { Write-Host \"It's valid.\" }"
#Pause
The #Pause is included only for users testing directly from the GUI, for others it can be omitted
Just to reduce the amount of code I used to prove a point, here's a more specific example for the task you've laid out in your question, i.e. determining whether the hour is odd or even:
#powershell.exe -NoP "If (((Get-Date).Hour %% 2) -Eq 1) { Write-Host \"It's not valid.\" } Else { Write-Host \"It's valid.\" }"
#Pause
Once again the pause is only required for users invoking the batch file via the GUI.
And because inevitably, you're going to tell us that you're not really wanting to print messages to the screen, but to perform different actions based upon the odd or even result:
#For /F %%G In ('powershell.exe -NoP "(Get-Date).Hour %% 2"') Do #If %%G Equ 1 (Echo It's not valid) Else Echo It's Valid.
#Pause
FOR /F %%a IN ('Powershell -Nop -c "Get-Date -Format 'HH'"') DO SET getcurrHour=%%a
set /a "check=(1%getcurrhour%-100) %%2"
if "%check%" == "0" (
echo even hour
) else (
echo odd hour
)
I guess, the line set /a "check=(1%getcurrhour%-100) %%2 needs some explanation:
set /a also knows octal numbers. They start with a zero. 08 and 09 start with a zero, but are not valid octal numbers, so we would get a syntax error. So we precede it with a 1 and subtract 100 from that to get a valid decimal number (8) The we simply do a MOD 2 to get a zero for even numbers and a one for odd numbers.
You need to test each value in the loop, not set the last value and test.
There is another issue however. Powershell's date is returned as HH which will do:
02
etc
22
Where your for /L loop gives:
2
etc
22
Meaning for some numbers it will not be true. So we need to test if the loop is single digit or double, if single we add a leading 0
#echo off
setlocal enabledelayedexpansion
for /f %%a in ('Powershell -Nop -c "Get-Date -Format 'HH'"') do set "getcurrHour=%%a"
for /L %%a IN (0,2,22) do (
set "li=%%~a"
if "!li:~1!" == "" set "li=0!li!"
if %getcurrHour% equ !li! (
echo It's valid.
) else (
echo It's not valid.
)
)

How to create folder by Date time in batch file

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

How to get locale-independent modified time and creation time of a file in batch?

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

Error with If-Else statement combine with Math in .bat file

It's supose to be simples, but i can't get it working ! Maybe someone could help...
I just need a program that check if '07503.csv' file exists, and than '07504.csv', '07505.csv'...until '07552.csv'. Here i'm supose to end the program (it's simplified so you can understand my problem).
This works:
SET angle=075
SET velocity=03
SET finalfilename=.csv
SET endofsequency=07552
SETLOCAL EnableDelayedExpansion
:loop
SET currentsequency=%angle%%velocity%
SET fullfilename=%currentsequency%%finalfilename%
:CHECK_FILES
IF EXIST %fullfilename% (
ECHO FILE FOUND: %fullfilename%
GOTO :GO_TROUGHT
) ELSE (
ECHO FILE NOT FOUND: %fullfilename%
GOTO :WRITE_LOG
)
:WRITE_LOG
ECHO %time% missing: %fullfilename%
ECHO %time% missing: %fullfilename% >> FilesMissed.txt
:GO_TROUGHT
FOR /F "tokens=* delims=0" %%A IN ("%velocity%") DO SET velocity=%%A
SET /A velocity+=1
SET velocity=000%velocity%
SET velocity=%velocity:~-2%
PAUSE
IF %currentsequency% NEQ %endofsequency% GOTO loop
:END
PAUSE
But with IF-ElSE statement does not:
SET angle=075
SET velocity=03
SET finalfilename=.csv
SETLOCAL EnableDelayedExpansion
:loop
SET currentsequency=%angle%%velocity%
SET fullfilename=%currentsequency%%finalfilename%
:CHECK_FILES
IF EXIST %fullfilename% (
ECHO FILE FOUND: %fullfilename%
GOTO :GO_TROUGHT
) ELSE (
ECHO FILE NOT FOUND: %fullfilename%
GOTO :WRITE_LOG
)
:WRITE_LOG
ECHO %time% missing: %fullfilename%
ECHO %time% missing: %fullfilename% >> FilesMissed.txt
:GO_TROUGHT
IF "%velocity%" NEQ "52" (
FOR /F "tokens=* delims=0" %%A IN ("%velocity%") DO SET velocity=%%A
SET /A velocity+=1
SET velocity=000%velocity%
SET velocity=%velocity:~-2%
) ELSE (
GOTO :END
)
PAUSE
GOTO :loop
:END
PAUSE
My question is why? What's happening? Can't i use FOR inside a IF-ELSE ? Idk ...
Regards,
Without reading closely - will using this help instead?
IF "%velocity%" EQU "52" goto :END
Looking a bit closer - it is an issue with delayed expansion. You need to enable it and then use !variable! instead of %variable% when inside parenthesis.
EDIT: try this with delayed expansion. The first line is changed, and the two last SET velocity= lines are changed.
setlocal enabledelayedexpansion
SET angle=075
SET velocity=03
SET finalfilename=.csv
SETLOCAL EnableDelayedExpansion
:loop
SET currentsequency=%angle%%velocity%
SET fullfilename=%currentsequency%%finalfilename%
:CHECK_FILES
IF EXIST %fullfilename% (
ECHO FILE FOUND: %fullfilename%
GOTO :GO_TROUGHT
) ELSE (
ECHO FILE NOT FOUND: %fullfilename%
GOTO :WRITE_LOG
)
:WRITE_LOG
ECHO %time% missing: %fullfilename%
ECHO %time% missing: %fullfilename% >> FilesMissed.txt
:GO_TROUGHT
IF "%velocity%" NEQ "52" (
FOR /F "tokens=* delims=0" %%A IN ("%velocity%") DO SET velocity=%%A
SET /A velocity+=1
SET velocity=000!velocity!
SET velocity=!velocity:~-2!
) ELSE (
GOTO :END
)
PAUSE
GOTO :loop
:END
PAUSE
This is the way I would do that:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET angle=075
SET "velocity=103" // Will use just 2 last digits of velocity
SET finalfilename=.csv
SET "endVelocity=152" // The same here...
SET /A numberOfValues=endVelocity - velocity + 1
for /L %%i in (1,1,%numberOfValues%) do (
SET fullfilename=%angle%!velocity:~-2!%finalfilename%
rem CHECK_FILES
IF EXIST !fullfilename! (
ECHO FILE FOUND: !fullfilename!
) ELSE (
ECHO FILE NOT FOUND: !fullfilename!
rem WRITE_LOG
ECHO !time! missing: !fullfilename!
ECHO !time! missing: !fullfilename! >> FilesMissed.txt
)
SET /A velocity+=1
PAUSE
)
PAUSE
Like #Aacini's answer, the following uses a FOR /L loop, but the method is slightly different:
#ECHO OFF
SET angle=075
SET startvelocity=3
SET endvelocity=52
SET ext=.csv
SET /A startnum=1%angle%*100+startvelocity
SET /A endnum=1%angle%*100+endvelocity
FOR /L %%i IN (%startnum%,1,%endnum%) DO (
SET "filename=%%i%ext%"
SETLOCAL EnableDelayedExpansion
IF EXIST !filename:~1! (
ECHO FILE FOUND: !filename:~1!
) ELSE (
ECHO FILE NOT FOUND: !filename:~1!
SET "logline=!time! missing: !filename:~1!"
ECHO !logline!
ECHO !logline!>> FilesMissed.txt
)
ENDLOCAL
)
That is, the loop is iterating over values like
107503
107504
107505
...
The leading 1 was added to preserve the 0 before the 75. (Leading 0s are lost in arithmetical operations.)
In the loop body, the value of the loop variable is used to construct a file name:
107503.csv
107504.csv
...
The leading 1 is later dropped (using ~1 when expanding the name).
Additionally, in case what you are writing to the FilesMissed.txt file is always meant to be duplicated on the screen, I introduced a variable to show how you could make sure the contents is duplicated exactly, allowing you to make changes to the formatting of the line only once. (Could be especially useful if you intended to additionally write the same line to other files.)

Finishing touches / tweaks to batch file renamer for video

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

Resources