Delete files based on MD5 hash - 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_:

Related

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

Is it possible to query a file or process hash using wmi?

I searched for any way to query a process hash.
assuming I was able to retrive the ExecutablePath using Win32_Process,
I would like to query the file's hash.
I'm trying to avoid using powershell but to achieve the same functiallity of "Get-FileHash".
Thank You!
edit:
I have tried to use win32_filespecification that supplied md5checksum, the problem was i could not find the relevant files (such as notepad.exe).
Here is a batch file to test :
#echo off
Title Get Notepad Hash
Set "App_Path=%windir%\system32\notepad.exe"
echo "%App_Path%"
#for /f "tokens=2 skip=3 delims= " %%a in ('Powershell Get-FileHash "%App_Path%"') do echo SHA256=%%a
Pause & Exit
EDIT :
Get Process File Hash using WMIC and Certutil in command line
You can give a try for the second batch file :
#echo off
cls & color 9E & Mode 95,5
Title Get Process File Hash using WMIC and Certutil in command line
Set "TmpFile=%~dpn0_Tmp.txt"
Set "LogPathExe=%~dpn0_PathExe.txt"
Set "Hashes=%~dpn0_Hashes.txt"
echo(
echo( ===========================================================
echo( Please wait a while ... Working is in progress....
echo( ===========================================================
Setlocal EnableDelayedExpansion
> "!TmpFile!" (
#for /f "delims=" %%a in ('wmic process get ExecutablePath /format:list') do (
#For /F "tokens=2 delims==" %%b in ("%%a") do (
set "Exe=%%b"
If not defined Exe Set !Exe!
echo "!Exe!"
)
)
)
Call :RemoveDuplicateEntry "!TmpFile!" "!LogPathExe!"
Del "!TmpFile!"
> "!Hashes!" (
#for /f "delims=" %%a in ('Type "!LogPathExe!"') do (
#for /f "skip=1 delims=" %%H in ('CertUtil -hashfile "%%~a" SHA256 ^| findstr /i /v "CertUtil"') do set "H=%%H"
echo %%a=!H: =!
)
)
)
If Exist "!Hashes!" Start "" "!Hashes!" & Exit
::----------------------------------------------------
:RemoveDuplicateEntry <InputFile> <OutPutFile>
Powershell ^
$Contents=Get-Content '%1'; ^
$LowerContents=$Contents.ToLower(^); ^
$LowerContents ^| select -unique ^| Out-File '%2'
Exit /b
::----------------------------------------------------
The third batch script to check hashes on virustotal :
#echo off
cls & color 9E & Mode 95,5
Title Get Process File Hash using WMIC and Certutil in command line
Set "TmpFile=%~dpn0_Tmp.txt"
Set "LogPathExe=%~dpn0_PathExe.txt"
Set "Hashes=%~dpn0_Hashes.txt"
Set "Hash2Check_VirusTotal=%~dpn0_Hash2Check_VirusTotal.txt"
If Exist "%Hash2Check_VirusTotal%" Del "%Hash2Check_VirusTotal%"
echo(
echo( ===========================================================
echo( Please wait a while ... Working is in progress....
echo( ===========================================================
Setlocal EnableDelayedExpansion
> "!TmpFile!" (
#for /f "delims=" %%a in ('wmic process get ExecutablePath /format:list') do (
#For /F "tokens=2 delims==" %%b in ("%%a") do (
set "ExecutablePath=%%b"
If not defined ExecutablePath Set !ExecutablePath!
echo "!ExecutablePath!"
)
)
)
Call :RemoveDuplicateEntry "!TmpFile!" "!LogPathExe!"
Del "!TmpFile!"
> "!Hashes!" (
#for /f "delims=" %%a in ('Type "!LogPathExe!"') do (
#for /f "skip=1 delims=" %%H in ('CertUtil -hashfile "%%~a" SHA256 ^| findstr /i /v "CertUtil"') do set "H=%%H"
echo %%a=!H: =!
>> "!Hash2Check_VirusTotal!" echo https://www.virustotal.com/old-browsers/file/!H: =!
)
)
)
cls
Echo(
Echo( Did you want to check the executable on Virustotal ? Just Type "Y" Or any key to Quit !
Set /p "Check="
If /I [!check!] EQU [Y] (
#for /f "delims=" %%a in ('Type "!Hash2Check_VirusTotal!"') do ( Start "Chek SHA256 on VIRUSTOTAL" %%a & Timeout /T 10 /nobreak>nul)
) else (
If Exist "!Hashes!" Start "" "!Hashes!" & Exit
)
Exit
::----------------------------------------------------
:RemoveDuplicateEntry <InputFile> <OutPutFile>
Powershell ^
$Contents=Get-Content '%1'; ^
$LowerContents=$Contents.ToLower(^); ^
$LowerContents ^| select -unique ^| Out-File '%2'
Exit /b
::----------------------------------------------------

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.

how to hide the entered password with ******* in batch programming? [duplicate]

This question already has answers here:
Can I mask an input text in a bat file?
(19 answers)
Closed 6 years ago.
I have a requirement like whenever we execute a test.bat file then it should ask enter password and entered password should be hidden with *****.
Is there any simplest way in batch programming for the above requirement?
I have written the below script using PowerShell is it fine/recommended to use PowerShell for this or any other simplest way is available?
#ECHO OFF
setlocal
set "psCommand=powershell -Command "$pword = read-host 'Enter password:' -AsSecureString ; ^
$BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /F "usebackq delims=" %%G in (`%psCommand%`) do set password=%%G
echo "%password%"
endlocal
Also suggest how to terminate the batch file as Ctrl+C is not working?
Give a try with this little example :
#echo off
Title %~n0 by Hackoo 2016
Mode 50,5 & Color 0E
:CreatePassword
cls & Color 0E
setlocal DisableDelayedExpansion
Call :InputPassword "Please choose your password" pass1
Call :InputPassword "Please confirm your password" pass2
setlocal EnableDelayedExpansion
If !pass1!==!pass2! ( Goto:Good ) Else ( Goto:Bad )
::***********************************
:InputPassword
Cls
echo.
echo.
set "psCommand=powershell -Command "$pword = read-host '%1' -AsSecureString ; ^
$BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set %2=%%p
Goto :eof
::***********************************
:Good
Color 0B
Cls
echo.
echo Good password
::TimeOut /T 2 /NoBreak>nul
echo Your password stored as : "!Pass2!" without quotes
pause>nul
Goto :Eof
::***********************************
:Bad
Color 0C
Cls
echo.
echo Wrong password try again
::TimeOut /T 2 /NoBreak>nul
echo Press any key to retry again
pause>nul
Goto :CreatePassword
::***********************************
And you can also give a try for this complete example Folder Loker.bat
Edit on 31/03/2016 # 14:43
Another way in pur batch based on replace command
#Echo Off
SetLocal EnableExtensions EnableDelayedExpansion
Set /P "=Enter a Password:" < Nul
Call :PasswordInput
Echo(Your input was:!Line!
pause
Goto :Eof
:PasswordInput
::Author: Carlos Montiers Aguilera
::Last updated: 20150401. Created: 20150401.
::Set in variable Line a input password
For /F skip^=1^ delims^=^ eol^= %%# in (
'"Echo(|Replace.exe "%~f0" . /U /W"') Do Set "CR=%%#"
For /F %%# In (
'"Prompt $H &For %%_ In (_) Do Rem"') Do Set "BS=%%#"
Set "Line="
:_PasswordInput_Kbd
Set "CHR=" & For /F skip^=1^ delims^=^ eol^= %%# in (
'Replace.exe "%~f0" . /U /W') Do Set "CHR=%%#"
If !CHR!==!CR! Echo(&Goto :Eof
If !CHR!==!BS! (If Defined Line (Set /P "=!BS! !BS!" <Nul
Set "Line=!Line:~0,-1!"
)
) Else (Set /P "=*" <Nul
If !CHR!==! (Set "Line=!Line!^!"
) Else Set "Line=!Line!!CHR!"
)
Goto :_PasswordInput_Kbd
And this is another version improved by aGerman
#echo off & setlocal
Title %~n0
Mode 50,5 & Color 9E
Set /P "Pass1=Please choose your Password:" < Nul
call :HInput Pass1
echo Input length is %errorlevel%
setlocal EnableDelayedExpansion
echo Your password is !Pass1!
pause
cls
Set /P "Pass2=Please confirm your Password:" < Nul
call :HInput Pass2
echo Input length is %errorlevel%
echo Your password is !Pass2!
pause
cls
If !Pass1!==!Pass2! (echo the two passwords are the same
) else (echo the two passwords does not match)
pause
goto :eof
:HInput [ByRef_VarName]
:: inspired by Carlos
if "%__HI__%" neq "__HI__" (
setlocal DisableDelayedExpansion EnableExtensions
set "CR=" &set "S=" &set "N=0" &set "__HI__=__HI__"
for /f "skip=1" %%i in ('echo(^|replace ? . /u /w') do if not defined CR set "CR=%%i"
for /f %%i in ('"prompt $H &for %%b in (1) do rem"') do set "BS=%%i"
)
set "C="
for /f skip^=1^ delims^=^ eol^= %%i in ('replace ? . /u /w') do if not defined C set "C=%%i"
setlocal EnableDelayedExpansion EnableExtensions
if "!CR!"=="!C!" (
echo(
if "%~1"=="" (
echo(!S!
endlocal &endlocal &exit /b %N%
) else (
if defined S (
for /f delims^=^ eol^= %%i in ("!S!") do endlocal &endlocal &set "%~1=%%i" &exit /b %N%
) else endlocal &endlocal &set "%~1=" &exit /b 0
)
)
if "!BS!"=="!C!" (
set "C="
if defined S set /a "N -= 1" &set "S=!S:~,-1!" &<nul set /p "=%BS% %BS%"
) else set /a "N += 1" &<nul set /p "=*"
if not defined S (
endlocal &set "N=%N%" &set "S=%C%"
) else for /f delims^=^ eol^= %%i in ("!S!") do endlocal &set "N=%N%" &set "S=%%i%C%"
goto HInput

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