Batch - Compare file date with actual date - date

I get the file date from a file:
for %%x in (%file_test%) do set file_date_test=%%~tx
And then I get the system date:
set year=%date:~-4%
set month=%date:~3,2%
if "%month:~0,1%" == " " set month=0%month:~1,1%
set day=%date:~0,2%
if "%day:~0,1%" == " " set day=0%day:~1,1%
set hour=%time:~0,2%
if "%hour:~0,1%" == " " set hour=0%hour:~1,1%
set min=%time:~3,2%
if "%min:~0,1%" == " " set min=0%min:~1,1%
And then do an if statement with goto:
IF %file_date_test% LSS %system_date_test% goto SOME
How can I compare both dates? I would like to check if the file date has more than 24H.
Which is the best way to do that? Can I use forfiles to do it?

Edited forfiles command will not even look at the hour of the file, so the previous answer (at the bottom in case someone find it useful) will not work if the file has different date but less than 24h.
For an alternative
robocopy "c:\backup" "c:\backup" "test.bak" /l /nocopy /is /minage:1 > nul
if errorlevel 1 (
echo MATCH
) else (
echo NO_MATCH
)
At least in windows 7, the robocopy command look at the timestamp of the file to determine its age.
Previous answer
You can use forfiles checking the errorlevel of the operation
#echo off
setlocal enableextensions disabledelayedexpansion
set "file_test=c:\backups\test.bak"
for %%a in ("%file_test%") do (
forfiles /p "%%~dpa." /m "%%~nxa" /d -1 >nul 2>nul && echo MATCH || echo NO MATCH
)
Or
#echo off
setlocal enableextensions disabledelayedexpansion
forfiles /p "c:\backups" /m "test.bak" /d -1 >nul 2>nul
if errorlevel 1 (
echo NO_MATCH
) else (
echo MATCH
)

Related

How can I use Explorer in Powershell to select a file to be processed within my Powershell script [duplicate]

Typically, asking the user to supply a file name to a batch script is a messy affair, requiring no misspellings, quotes around paths with spaces, and so forth. Unfortunately, users aren't well-known for accuracy. In situations where input file location is not known until runtime, using a GUI for file selection input reduces the likelihood of user error.
Is there a way to invoke a File... Open style gui file chooser or folder chooser from a Windows batch script?
If the script user has PowerShell or .NET installed, it is possible. See the answer below.
I'm also interested to see what other solutions anyone else can offer.
File Browser
Update 2016.3.20:
Since PowerShell is a native component of pretty much all modern Windows installations nowadays, I'm declaring the C# fallback as no longer necessary. If you still need it for Vista or XP compatibility, I moved it to a new answer. Starting with this edit, I'm rewriting the script as a Batch + PowerShell hybrid and incorporating the ability to perform multi-select. It's profoundly easier to read and to tweak as needed.
<# : chooser.bat
:: launches a File... Open sort of file chooser and outputs choice(s) to the console
:: https://stackoverflow.com/a/15885133/1683264
#echo off
setlocal
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
echo You chose %%~I
)
goto :EOF
: end Batch portion / begin PowerShell hybrid chimera #>
Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
This results in a file chooser dialog.
The result of a selection outputs You chose C:\Users\me\Desktop\tmp.txt to the console. If you want to force single file selection, just change the $f.Multiselect property to $false.
(PowerShell command mercilessly leeched from the Just Tinkering Blog.) See the OpenFileDialog Class documentation for other properties you can set, such as Title and InitialDirectory.
Folder Browser
Update 2015.08.10:
Since there is already a COM method for invoking a folder chooser, it's pretty easy to build a PowerShell one-liner that can open the folder chooser and output the path.
:: fchooser.bat
:: launches a folder chooser and outputs choice to the console
:: https://stackoverflow.com/a/15885133/1683264
#echo off
setlocal
set "psCommand="(new-object -COM 'Shell.Application')^
.BrowseForFolder(0,'Please choose a folder.',0,0).self.path""
for /f "usebackq delims=" %%I in (`powershell %psCommand%`) do set "folder=%%I"
setlocal enabledelayedexpansion
echo You chose !folder!
endlocal
In the BrowseForFolder() method, the fourth argument specifies the root of the hierarchy. See ShellSpecialFolderConstants for a list of valid values.
This results in a folder chooser dialog.
The result of a selection outputs You chose C:\Users\me\Desktop to the console.
See the FolderBrowserDialog class documentation for other properties you can set, such as RootFolder. My original .NET System.Windows.Forms PowerShell and C# solutions can be found in revision 4 of this answer if needed, but this COM method is much easier to read and maintain.
This should work from XP upwards and does'nt require an hibrid file, it just runs mshta with a long command line:
#echo off
set dialog="about:<input type=file id=FILE><script>FILE.click();new ActiveXObject
set dialog=%dialog%('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);
set dialog=%dialog%close();resizeTo(0,0);</script>"
for /f "tokens=* delims=" %%p in ('mshta.exe %dialog%') do set "file=%%p"
echo selected file is : "%file%"
pause
Windows Script Host
File Selection
Windows XP had a mysterious UserAccounts.CommonDialog WSH object which allowed VBScript and JScript to launch the file selection prompt. Apparently, that was deemed a security risk and removed in Vista.
Folder Selection
However, the WSH Shell.Application object BrowseForFolder method will still allow the creation of a folder selection dialog. Here's a hybrid batch + JScript example. Save it with a .bat extension.
#if (#a==#b) #end /*
:: fchooser2.bat
:: batch portion
#echo off
setlocal
for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0"') do (
echo You chose %%I
)
goto :EOF
:: JScript portion */
var shl = new ActiveXObject("Shell.Application");
var folder = shl.BrowseForFolder(0, "Please choose a folder.", 0, 0x00);
WSH.Echo(folder ? folder.self.path : '');
In the BrowseForFolder() method, the fourth argument specifies the root of the hierarchy. See ShellSpecialFolderConstants for a list of valid values.
A file / folder selection may be done with pure Batch, as shown below. Of course, the feel and look is not as pleasant as a GUI, but it works very well and in my opinion it is easier to use than the GUI version. The selection method is based on CHOICE command, so it would require to download it in the Windows versions that don't include it and slightly modify its parameters. Of course, the code may be easily modified in order to use SET /P instead of CHOICE, but this change would eliminate the very simple and fast selection method that only requires one keypress to navigate and select.
#echo off
setlocal
rem Select a file or folder browsing a directory tree
rem Antonio Perez Ayala
rem Usage examples of SelectFileOrFolder subroutine:
call :SelectFileOrFolder file=
echo/
echo Selected file from *.* = "%file%"
pause
call :SelectFileOrFolder file=*.bat
echo/
echo Selected Batch file = "%file%"
pause
call :SelectFileOrFolder folder=/F
echo/
echo Selected folder = "%folder%"
pause
goto :EOF
:SelectFileOrFolder resultVar [ "list of wildcards" | /F ]
setlocal EnableDelayedExpansion
rem Process parameters
set "files=*.*"
if "%~2" neq "" (
if /I "%~2" equ "/F" (set "files=") else set "files=%~2"
)
rem Set the number of lines per page, max 34
set "pageSize=30"
set "char=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
rem Load current directory contents
set "name[1]=<DIR> .."
:ProcessThisDir
set "numNames=1"
for /D %%a in (*) do (
set /A numNames+=1
set "name[!numNames!]=<DIR> %%a"
)
for %%a in (%files%) do (
set /A numNames+=1
set "name[!numNames!]= %%a"
)
set /A numPages=(numNames-1)/pageSize+1
rem Show directory contents, one page at a time
set start=1
:ShowPage
set /A page=(start-1)/pageSize+1, end=start+pageSize-1
if %end% gtr %numNames% set end=%numNames%
cls
echo Page %page%/%numPages% of %CD%
echo/
if %start% equ 1 (set base=0) else set "base=1"
set /A lastOpt=pageSize+base, j=base
for /L %%i in (%start%,1,%end%) do (
for %%j in (!j!) do echo !char:~%%j,1! - !name[%%i]!
set /A j+=1
)
echo/
rem Assemble the get option message
if %start% equ 1 (set "mssg=: ") else (set "mssg= (0=Previous page")
if %end% lss %numNames% (
if "%mssg%" equ ": " (set "mssg= (") else set "mssg=%mssg%, "
set "mssg=!mssg!Z=Next page"
)
if "%mssg%" neq ": " set "mssg=%mssg%): "
:GetOption
choice /C "%char%" /N /M "Select desired item%mssg%"
if %errorlevel% equ 1 (
rem "0": Previous page or Parent directory
if %start% gtr 1 (
set /A start-=pageSize
goto ShowPage
) else (
cd ..
goto ProcessThisDir
)
)
if %errorlevel% equ 36 (
rem "Z": Next page, if any
if %end% lss %numNames% (
set /A start+=pageSize
goto ShowPage
) else (
goto GetOption
)
)
if %errorlevel% gtr %lastOpt% goto GetOption
set /A option=start+%errorlevel%-1-base
if %option% gtr %numNames% goto GetOption
if defined files (
if "!name[%option%]:~0,5!" neq "<DIR>" goto endSelect
) else (
choice /C OS /M "Open or Select '!name[%option%]:~7!' folder"
if errorlevel 2 goto endSelect
)
cd "!name[%option%]:~7!"
goto ProcessThisDir
:endSelect
rem Return selected file/folder
for %%a in ("!name[%option%]:~7!") do set "result=%%~Fa"
endlocal & set "%~1=%result%
exit /B
Other solution with direct run PowerShell command in Batch
rem preparation command
set pwshcmd=powershell -noprofile -command "&{[System.Reflection.Assembly]::LoadWithPartialName('System.windows.forms') | Out-Null;$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog; $OpenFileDialog.ShowDialog()|out-null; $OpenFileDialog.FileName}"
rem exec commands powershell and get result in FileName variable
for /f "delims=" %%I in ('%pwshcmd%') do set "FileName=%%I"
echo %FileName%
Batch + PowerShell + C# polyglot solution
This is the same solution as the Batch + PowerShell hybrid, but with the C# fallback stuff re-added for XP and Vista compatibility. Multiple file selection has been added at xNightmare67x's request.
<# : chooser_XP_Vista.bat
:: // launches a File... Open sort of file chooser and outputs choice(s) to the console
:: // https://stackoverflow.com/a/36156326/1683264
#echo off
setlocal enabledelayedexpansion
rem // Does powershell.exe exist within %PATH%?
for %%I in ("powershell.exe") do if "%%~$PATH:I" neq "" (
set chooser=powershell -noprofile "iex (${%~f0} | out-string)"
) else (
rem // If not, compose and link C# application to open file browser dialog
set "chooser=%temp%\chooser.exe"
>"%temp%\c.cs" (
echo using System;
echo using System.Windows.Forms;
echo class dummy {
echo public static void Main^(^) {
echo OpenFileDialog f = new OpenFileDialog^(^);
echo f.InitialDirectory = Environment.CurrentDirectory;
echo f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
echo f.ShowHelp = true;
echo f.Multiselect = true;
echo f.ShowDialog^(^);
echo foreach ^(String filename in f.FileNames^) {
echo Console.WriteLine^(filename^);
echo }
echo }
echo }
)
for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*csc.exe"') do (
if not exist "!chooser!" "%%I" /nologo /out:"!chooser!" "%temp%\c.cs" 2>NUL
)
del "%temp%\c.cs"
if not exist "!chooser!" (
echo Error: Please install .NET 2.0 or newer, or install PowerShell.
goto :EOF
)
)
rem // Do something with the chosen file(s)
for /f "delims=" %%I in ('%chooser%') do (
echo You chose %%~I
)
rem // comment this out to keep chooser.exe in %temp% for faster subsequent runs
del "%temp%\chooser.exe" >NUL 2>NUL
goto :EOF
:: // end Batch portion / begin PowerShell hybrid chimera #>
Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
For a folder chooser for XP or Vista, use either the WSH solution or npocmaka's HTA solution.
Two more ways.
1.Using a hybrid .bat/hta (must be saved as a bat) script .It can use vbscript or javascript but the example is with javascrtipt.Does not create temp files.Selecting folder is not so easy and will require an external javascript libraries , but selecting file is easy
<!-- : starting html comment
:: FileSelector.bat
#echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
set "file=%%~fp"
)
echo/
if not "%file%" == "" (
echo selected file is : %file%
)
echo/
exit /b
-->
<Title>== FILE SELECTOR==</Title>
<body>
<script language='javascript'>
function pipeFile() {
var file=document.getElementById('file').value;
var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
close(fso.Write(file));
}
</script>
<input type='file' name='file' size='30'>
</input><hr><button onclick='pipeFile()'>Submit</button>
</body>
1.1 - without submit form proposed by rojo (see comments):
<!-- : starting html comment
:: FileSelector.bat
#echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
set "file=%%~fp"
)
echo/
if not "%file%" == "" (
echo selected file is : "%file%"
)
echo/
exit /b
-->
<Title>== FILE SELECTOR==</Title>
<body>
<script language='javascript'>
function pipeFile() {
var file=document.getElementById('file').value;
var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
close(fso.Write(file));
}
</script>
<input id='file' type='file' name='file' size='30' onchange='pipeFile()' >
</input>
<hr>
<button onclick='pipeFile()'>Submit</button>
<script>document.getElementById('file').click();</script>
</body>
2.As you already using powershell/net you can create selfcompiled jscript.net hybrid.It will not require temp cs file for compilation and will directly use the built-in jscrript.net compiler.There's no need of powershell too and the code is far more readable:
#if (#X)==(#Y) #end /* JScript comment
#echo off
:: FolderSelectorJS.bat
setlocal
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
set "jsc=%%v"
)
if not exist "%~n0.exe" (
"%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
)
for /f "tokens=* delims=" %%p in ('"%~n0.exe"') do (
set "folder=%%p"
)
if not "%folder%" == "" (
echo selected folder is %folder%
)
endlocal & exit /b %errorlevel%
*/
import System;
import System.Windows.Forms;
var f=new FolderBrowserDialog();
f.SelectedPath=System.Environment.CurrentDirectory;
f.Description="Please choose a folder.";
f.ShowNewFolderButton=true;
if( f.ShowDialog() == DialogResult.OK ){
Console.Write(f.SelectedPath);
}
I will leave an 'echo' even to verify that multiple choice works in this code
echo off
set cmd=Add-Type -AssemblyName System.Windows.Forms;$f=new-object Windows.Forms.OpenFileDialog;$f.InitialDirectory= [environment]::GetFolderPath('Desktop');$f.Filter='Text Files(*.txt)^|*.txt^|All Files(*.*)^|*.*';$f.Multiselect=$true;[void]$f.ShowDialog();if($f.Multiselect) {$f.FileNames}else{$f.FileName}
set pwshcmd=powershell -noprofile -command "&{%cmd%}"
for /f "tokens=* delims=" %%I in ('%pwshcmd%') do call :sum "%%I" ret
echo =========
echo --%ret%--
pause
exit /B
:sum [mud] [ret]
echo "%~1"
set FileName=%FileName% "%~1"
set ret=%FileName%
exit /B
I has been wrote my own portable solution:
https://github.com/andry81/contools/tree/HEAD/Utilities/src/_gui/wxFileDialog/
You can download executable from here:
https://github.com/andry81/contools/tree/HEAD/Utilities/bin/contools/wxFileDialog.exe
The utility has dependency on wxWidgets 3.1.x, so you can actually build it for other operating systems.

Calling powershell function in batch script

Hoping someone can point me in the right direction. Have a working remote PC info scanning tool that collects computer name, serial number and model. Been trying to get the monitor info added for so time and found this Powershell script and have been trying to get intergraded without success.
Powershell function;
$Monitors = Get-WmiObject WmiMonitorID -Namespace root\wmi
$LogFile = ".\MonInfo.csv"
function Decode {
If ($args[0] -is [System.Array]) {
[System.Text.Encoding]::ASCII.GetString($args[0])
}
Else {
"Not Found"
}
}
ForEach ($Monitor in $Monitors) {
$Manufacturer = Decode $Monitor.ManufacturerName -notmatch 0
$Name = Decode $Monitor.UserFriendlyName -notmatch 0
$Serial = Decode $Monitor.SerialNumberID -notmatch 0
echo $Manufacturer, $Name, $Serial" >> $LogFile
}
Here's the network scan batch script I been using. (Basic info scan via ping and get info from remoter systems via WMI)
#echo off
cls
color 5f
setlocal EnableDelayedExpansion
net session >nul 2>&1
if %errorlevel% neq 0 set errormsg=This program must be run as Administrator& goto ERRORDISP
set "ip="
for /f "tokens=2 delims=:" %%a in ('ipconfig ^| findstr /c:"IPv4 Address"') do set ip=%%a
if not defined ip (set errormsg=No IP address detected - check network cable& goto ERRORDISP)
set ip=%ip: =%
for /f "tokens=1,2,3,4 delims=." %%a in ("%ip%") do set oct1=%%a& set oct2=%%b& set oct3=%%c& set oct4=%%d
set subnet=%oct1%.%oct2%.%oct3%
set scan=0
set found=0
set foundsv=0
set ipstart=51
set ipend=170
:SCAN
set /a totalip=ipend-ipstart+1
set "_d=%date%"
set "_t=%time%"
set "log=scanLog%-d%-%_t%.csv"
echo IP,Name,Serial,Model > %log%
echo.
for /l %%a in (%ipstart%,1,%ipend%) do (
set "ip=%subnet%.%%a"
set /a scan=scan+1
set /a pct=scan*100/totalip
echo Scanning !ip!...
call :BAR !pct! 40 progbar
title Simple Scanner ^| !totalip!/!scan!/!found!/!foundsv! ^| [!progbar!] !pct!%%%
ping -n 1 -w 200 !ip! | find "TTL" >nul
if !errorlevel! equ 0 (
set "output="
set /a found=found+1
call :GETWMI !ip! "bios get serialnumber" serial
call :GETWMI !ip! "computersystem get model" model
call :GETWMI !ip! "computersystem get name" name
REM *** DO "SV WORKSTATION" THINGS HERE
set "output=!ip!,!name!,!serial!,!model! !MonSN!"
) else (
REM *** DO "NON-SV WORKSTATION" THINGS HERE
set "output=!ip!,!name!,!serial!,!model! !MonSN!"
)
echo !output! >> %log%
) else (
REM *** DO "WORKSTATION NOT DETECTED" THINGS HERE
)
)
:END
cls
color 2f
echo.
echo SCAN COMPLETE
echo ______________________________________________________________________
echo.
echo
echo Range: %subnet%.%ipstart% - %ipend%
echo Scanned: %scan%
echo Found total: %found%
echo Found SV: %foundsv%
echo ______________________________________________________________________
echo.
echo Opening log file %log%...
echo.
start /max %log%
echo
echo Press any key to exit...
pause>nul
exit
:GETWMI
set "_s="
set _r=%2
set _r=%_r:"=%
(for /f "tokens=2 delims==" %%b in ('wmic /failfast:on /node:%1 %_r% /value') do set _s=%%b) 2>nul
if not defined _s set "_s=ERROR"
set "%~3=%_s%"
goto :eof
:BAR
if not defined xbar call :initBAR %2
for /l %%b in (1,1,%2) do (
set /a bars=%2*%1/100
set /a spcs=%2-bars
set "obar="
for %%c in (!bars!) do set "obar=!obar!!xbar:~0,%%c!"
for %%c in (!spcs!) do set "obar=!obar!!xspc:~0,%%c!"
set %3=!obar!
)
goto :eof
:initBAR
set "xbar=" & for /l %%b in (1,1,%1) do set "xbar=!xbar!l"
set "xspc=" & for /l %%b in (1,1,%1) do set "xspc=!xspc! "
goto :eof
:ERRORDISP
cls
color cf
echo.
echo ^>^>^> ERROR ^<^<^<
echo.
echo %errormsg%
echo
echo Press any key to exit...
pause>nul
exit
I have also tried calling for the .ps1 yet the variables are always empty and the corp network requires Powershell scripts to have sign cert to run by them selves.
Long time ago I wrote the script to get monitor serial number from registry.
It takes only first monitor value. But you can change this script or convert to Powershell. Anyway you can see script logic: get EDID-number, then parse it.
#for /f %%i in ('#wmic path win32_desktopmonitor get pnpdeviceid ^|#find "DISPLAY"') do #set val="HKLM\SYSTEM\CurrentControlSet\Enum\%%i\Device Parameters"
#reg query %val% /v EDID>NUL
#if %errorlevel% GTR 0 #echo BAD EDID&EXIT
#for /f "skip=2 tokens=1,2,3*" %%a in ('#reg query %val% /v EDID') do #set edid=%%c
#set /A Y=%edid:~34,1%*16+%edid:~35,1%+1990
#echo.Manufactured: %Y%
#set id=%edid:000000FC00=#%
#for /f "tokens=1,2* delims=#" %%a in ("%id%") do #set id=%%b
#set id=%id:~0,22%
#setlocal enableextensions enabledelayedexpansion
#echo off
#for /L %%i in (0,2,20) do (
#set p=!id:~%%i,2!
#if !p!==0A #goto nxt
#set m=!m!0x!p!
)
#echo on
:nxt
#forfiles /p %windir%\system32 /m shell32.dll /c "cmd /c #echo.Model : !m!"
#endlocal
#set edid=%edid:000000FF00=#%
#for /f "tokens=1,2* delims=#" %%a in ("%edid%") do #set id=%%b
#set id=%id:~0,20%
#setlocal enableextensions enabledelayedexpansion
#for /L %%i in (0,2,18) do #set sn=!sn!0x!id:~%%i,2!
#forfiles /p %windir%\system32 /m shell32.dll /c "cmd /c #echo.S.N. : !sn!"
#endlocal

Batch script to convert .rej to CSV in order to parse useful data

The aim is to search multiple files with the extension of .rej, So i have a file that can easily display that information.
So I went in a completely different direction and uses CSV's because the info I needed is only 3 strings on every line.
#echo off
setlocal enabledelayedexpansion
For %%I in (*.rej) do (
(for /f "delims==" %%A in (%%I) do set string=%%A & echo !string::=,!) >> %%~nI_Tempout.tmp
(for /f "delims==" %%A in (%%~nI_Tempout.tmp) do set string=%%A & echo !string:[=,!) >> %%~nI_Tempout1.tmp
(for /f "delims=" %%A in (%%~nI_Tempout1.tmp) do Call :Split %%A ) > %%~nI_New.csv)
goto :Eof
:Split
#echo(%1,%9,%11
del *.tmp
File.rej
12.13.14 [-] [20190304][ VBTS 0 ] REJECTED:IM:2q1231231123124:II:123123123123:TM:1278391237912379128379:CAUSES:
12.13.16 [-] [20190304][ VBTS 0 ] REJECTED:IM:2q1231231123124:II:123123123123:TM:1278391237912379128379:CAUSES:
12.13.20 [-] [20190304][ VBTS 0 ] REJECTED:IM:2q1231231123124:II:123123123123:TM:1278391237912379128379:CAUSES:
However at the end the %11 prints %1 the 1,
I can only assume it detects %1 the echos the next 1
output
12.13.14,2q1231231123124,12.13.141
12.13.16,2q1231231123124,12.13.161
12.13.20,2q1231231123124,12.13.201
FINAL CODE
#echo off
setlocal enabledelayedexpansion
For %%I in (*.rej) do (
(for /f "delims==" %%A in (%%I) do set string=%%A & echo !string::=,!) >> %%~nI_Tempout.tmp
(for /f "delims==" %%A in (%%~nI_Tempout.tmp) do set string=%%A & echo !string:[=,!) >> %%~nI_Tempout1.tmp
(for /f "tokens=1,8,10 delims=," %%A in (%%~nI_Tempout1.tmp) do Call :Split %%A %%B %%C ) > %%~nI_New.csv)
goto :Eof
:Split
#echo(%1,%2,%3
del *.tmp
You parse your data to a temp file, parse that a second time to a second temp file and parse that a third time. That is inefficient. You can do it all with a single for /f loop, when you choose your tokens and delims wisely:
(for /f "tokens=1,7,11 delims=[-]: " %%A in ('type *.rej 2^>nul') do echo %%A,%%B,%%C)>file_New.csv
I'm not quite sure, if the tokens are right, because you didn't show your expected output, but you can easily adapt them to your needs.

Delete files based on MD5 hash

Using Windows command line (not powershell), I want to hash all files within the directory and then remove files that match a particular hash set contained within a text file.
I've considered using md5deep, but I'm unsure if the output of matched files can then be redirected into a delete command.
Any help gratefully received, thank you!
To add some detail; the files are in a directory called 'images'
md5deep.exe -r -b -x irrelevant_hashes.txt c:\images
This gives me a list of the files that I need to keep. Is it possible to redirect the output from MD5deep to move the 'good' files to another directory?
For a single md5 key in cmd line it is as easy as:
(Here using the 64bit variant).
set "KillMD5=00112233445566778899aabbccddeeff"
for /f "tokens=1*" %A in ('md5deep64.exe *.* 2^>mul') do #if %A==%KillMD5% #Echo del "%B"
For testing the del command is only echoed.
In a batch file double the % percent signs %%A/%%B
This use pure batch file, take use of CertUtil from windows, so no 3rd software need.
You only need provide the value for 2 variables:
set _nOp=irrelevant_hashes.txt :: file text with md5 data for files to delete
set "_path_gen=c:\images" :: path to files that will be delete.
In additional, put the txt file with md5 (in this code case irrelevant_hashes.txt) in the same folder of the files that you want to delete.
For generate a new md5 from files, and usin certUtil on command line:
type nul >"%temp%\MD5_to_del.txt" & cd /d "c:\images" & for /f "tokens=* delims= " %i in ('^<nul dir /o-d /on /b "c:\images\*.*"') do for /f "tokens=* delims= " %M in ('certutil -hashfile "%i" md5 ^| find /v ":"') do echo/%M>>"%temp%\MD5_to_del.txt"
For generate a new md5 from files, and using certUtil on a file.bat:
type nul >"%temp%\MD5_to_del.txt" & cd /d "c:\images" & for /f "tokens=* delims= " %%i in ('^<nul dir /o-d /on /b "c:\images\*.*"') do for /f "tokens=* delims= " %%M in ('certutil -hashfile "%%i" md5 ^| find /v ":"') do echo/%%M>>"%temp%\MD5_to_del.txt"
#echo off & setlocal EnableExtensions EnableDelayedExpansion
cls && mode con cols=120 lines=7 & cd /d "%~dp0"
set "'=^|"
set "_spc= "
set /a _cnt_left= 1 - 1
set /a _cnt_treated= 1 - 1
set /a _cnt_deleted= 1 - 1
set /a _cnt_keeped_= 1 - 1
set _type_hash=md5
set _show=0000000
set "_path_gen=c:\images"
cd /d !_path_gen! || set "_erro=!_path_gen! not exist?"&& goto :_error_:
set _n_deleted=%temp%\md5_not_deleted_.txt
set _y_deleted=%temp%\md5_was_deleted_.txt
(
if exist "!_n_deleted!" del /q /f "!_n_deleted!"
if exist "!_y_deleted!" del /q /f "!_y_deleted!"
) 2>nul >nul
if exist ".\irrelevant_hashes.txt" (
set _nOp=irrelevant_hashes.txt
) else (
set "_error= File irrelevant_hashes.txt not found"
goto :_error_:
)
set _hash_data=%temp%\hash_db\date_db.txt
if exist "!_hash_data!" (
del /q /f "!_hash_data!"
copy /y "!_nOp!" "!_hash_data!" 2>nul >nul || set _error=Copy !_nOp! to !_hash_data!
) else (
dir /ad "%temp%\hash_db\" 2>nul >nul | findstr /c:".." || mkdir "%temp%\hash_db"
copy /v "!_nOp!" "!_hash_data!" 2>nul >nul || set _error=Copy !_nOp! to !_hash_data!
)
for /f "delims= " %%T in ('forFiles /p "." /m "%~nx0" /c "cmd /c echo(0x09"') do set "_tab=%%T"
call set "_tab=%_tab:~0,1%"
for /f "tokens=* delims=^ " %%i in ('^<nul dir /o-d /on /b "!_path_gen!\*.*" 2^> nul ^| find "" /v /c ') do set _cnt_file=%%i
for /f "tokens=* delims= " %%f in ('dir /o-d /on /b "*.*" ^| findstr /i /v "!_nOp! %0" ') do (
for %%S in (cnt_treated cnt_deleted cnt_keeped_ cnt_left) do set _show_%%S=!_show!!_%%S!
set _file=%%~nxf
set "_file_hash=%%~dpnxf"
set /a _cnt_treated=!_cnt_treated! + 1
call :_get_hash_:
title Total files: !_show_cnt_treated:~-5! ^| Delete: !_show_cnt_deleted:~-5! ^| Keeped: !_show_cnt_keeped_:~-5! ^| File left: !_show_cnt_left:~-5!
)
(
if exist "!_n_deleted!" copy /y "!_n_deleted!" .
if exist "!_y_deleted!" del /y "!_y_deleted!" .
) 2>nul >nul
echo/ Total file treated: !_show_cnt_treated:~-5!
echo/ Total file deleted: !_show_cnt_deleted:~-5!
echo/ Total file keeped: !_show_cnt_keeped_:~-5!
goto :_end_of_file_:
:_get_hash_:
for /f "tokens=* delims= " %%i in ('certutil -hashfile "!_file_hash!" !_type_hash! ^| find /v ":"') do (
set "_hash=%%i"
call set "_hash=!_hash: =!"
call set _hash=!_hash!
for /f "tokens=* delims=" %%I in ('echo/%_tab%') do call set _file_hash=!_hash:%%I=!
call set _hash=!_hash!
for /f "tokens=* delims= " %%e in ('type "!_hash_data!" ^| findstr /i /l /c:"!_hash!"') do set _hash_db=%%e
if "!_hash_db!" equ "" set "_hash_db=- So, no found^!! not "
echo/ & echo/ File hash md5 from: "!_file!" & echo/
echo/!_spc!Hash !_type_hash!: !_hash!
echo/ Data hash md5 ^(db^): !_hash_db! equals?
call :_delete_md5_:
call set /a _cnt_left=!_cnt_file! - 1 - !_cnt_keeped_!
)
timeout /t 10 2>nul >nul
)
)
for %%C in (file_hash hash strn_hash strn_hash hash_nul hash_db) do set _%%C=
exit /b
:_delete_md5_:
if /i "!_hash_db!" equ "!_hash!" del /q /f "!_path_gen!\!_file!"
if not exist "!_path_gen!\!_file!" (
echo/!_file! !_strn_hash!>>"!_y_deleted!"
echo/!_spc!!_spc:~-10!!_hash! "!_file!" file was deleted^^!
call set /a _cnt_file=!_cnt_file! - 1
call set /a _cnt_deleted=!_cnt_deleted! + 1
exit /b
) else (
echo/!_file! !_strn_hash!>>"!_n_deleted!"
echo/!_spc!!_spc:~-10!!_hash! "!_file!" file not was deleted^^!
call set /a _cnt_keeped_=!_cnt_keeped_! + 1
exit /b
)
:_error_:
echo/ & echo/ & echo/ !_error!
goto :_end_of_file_:
:_end_of_file_:

create yesterday's date folder yyyy-mm-dd using .bat

I am attempting to create a prior date folder using the below script, and the problem is that it skips the month. To illustrate my point it ends up with 2016-2-. Thus, any relevant feedback on this would be appreciated.
Ps: Current date from my machine: 3/3/2016
Best,
#echo off
setlocal enabledelayedexpansion
cls
set vbs=%temp%\vbs.vbs
> %vbs% echo WScript.Echo DateAdd("d",-1,Date)
for /f "tokens=* delims=" %%a in ('cscript //nologo %vbs%') do (
set newfold=%%a
)
del %vbs%
for /f "tokens=1-3* delims=/ " %%1 in ("%newfold%") do (
set month=%%2&set date=%%3&set year=%%4
md !date!-!month!-!year!
echo New folder created = !date!-!month!-!year!
)
EDIT: VBScript using the Weekday() function
#echo off
setlocal EnableDelayedExpansion
cls
set vbs=%temp%\vbs.vbs
>%vbs% echo dateYesterday=DateAdd("d",-1,Date):
wdayYesterday=Weekday(dateYesterday):
If wdayYesterday=1 Then WScript.Echo DateAdd("d",-2,dateYesterday)
Else If wdayYesterday=7 Then WScript.Echo DateAdd("d",-1,dateYesterday)
Else WScript.Echo dateYesterday
for /f "tokens=* delims=" %%a in ('cscript //nologo %vbs%') do (
set newfold=%%a
)
echo dateYesterday = %newfold% ^(assumption: month/day/year^)
del %vbs%
for /f "tokens=1-3 delims=/ " %%1 in ("%newfold%") do (
set month=%%2
set day=%%1
set year=%%3
)
md %day%-%month%-%year%
echo New folder created = %day%-%month%-%year% ^(day/month/year^)
You confused the tokens in the 2nd for /f loop: assuming your date format is month/day/year, you need to change the set command line. Here is the corrected code:
#echo off
setlocal EnableDelayedExpansion
cls
set vbs=%temp%\vbs.vbs
> %vbs% echo WScript.Echo DateAdd("d",-1,Date)
for /f "tokens=* delims=" %%a in ('cscript //nologo %vbs%') do (
set newfold=%%a
)
echo Yesterday = %newfold% ^(assumption: month/day/year^)
del %vbs%
for /f "tokens=1-3 delims=/ " %%1 in ("%newfold%") do (
set month=%%2
set day=%%1
set year=%%3
)
md %day%-%month%-%year%
echo New folder created = %day%-%month%-%year% ^(day/month/year^)
Since the 2nd for /f loop iterates once only (like also the 1st one), I moved all commands but set outside, so there is no need for delayed expansion any more.
To cover also the EDIT of your question where you want the date of the previous business day (so Saturdays and Sundays do not count), you could just extend the temporary VBScript:
#echo off
setlocal EnableDelayedExpansion
cls
set vbs=%temp%\vbs.vbs
> %vbs% echo dateYesterday=DateAdd("d",-1,Date): wdayYesterday=Weekday(dateYesterday): If wdayYesterday=1 Then WScript.Echo DateAdd("d",-2,dateYesterday) Else If wdayYesterday=7 Then WScript.Echo DateAdd("d",-1,dateYesterday) Else WScript.Echo dateYesterday
for /f "tokens=* delims=" %%a in ('cscript //nologo %vbs%') do (
set newfold=%%a
)
echo Yesterday = %newfold% ^(assumption: month/day/year^)
del %vbs%
for /f "tokens=1-3 delims=/ " %%1 in ("%newfold%") do (
set month=%%2
set day=%%1
set year=%%3
)
md %day%-%month%-%year%
echo New folder created = %day%-%month%-%year% ^(day/month/year^)
This approach uses the Weekday() function (in the *.vbs script) to get the current day of week (1 is Sunday, 2 is Monday,..., 7 is Saturday).