Batch file for opening most recent Malwarebytes' Anti-Malware Log - batch-file

In Vista, I want to run a batch script to open the most recent file, based either on last modified date, or the date in the filename. It's for Malwarebytes' Anti-Malware logs in the %username&/appdata/roaming/Malwarebytes/Malwarebytes' Anti-Malware/Logs folder.
Log files are in this format here
mbam-log-2009-03-21 (00-20-21).txt
mbam-log-2009-03-21 (09-42-40).txt
mbam-log-2009-03-21 (11-02-43).txt
mbam-log-2009-03-21 (11-12-01).txt
mbam-log-2009-03-21 (12-01-42).txt
mbam-log-2009-03-21 (12-04-49).txt
mbam-log-2009-03-21 (14-01-41).txt
So its 24-hr format. I read on another page on here, and got this script here..
#echo off
dir *.txt /b /on > systext.bak
FOR /F %%i in (systext.bak) do set sysRunCommand=%%i
call %sysRunCommand%
del systext.bak /y
but it doesn't like the space in the filename.. always get an error.
Anyone have any ideas?

You actually have three problems in the script. The first is that %%i is likely to be set to the words with a filename- this can be fixed by using "delims=" in the for statement.
The second is that you need to quote spacey filenames in you call statement.
The third is that I'm not aware of a /y option for del, perhaps you mean del /f.
Amyway, give this one a shot:
#echo off
dir *.txt /b /on > systext.bak
FOR /F "delims=" %%i in (systext.bak) do set sysRunCommand=%%i
call "%sysRunCommand%"
del /f systext.bak

The following one-line batch file will open the most recently modified file:
for /f "usebackq delims=" %%i in (`dir /b /o-d`) do #start "%%i"&goto :eof
Using dir strikes me as much simpler than trying to dissect the date in the filename. You can also order by filename (as the date format is somewhat ISO-8601-ish is sorts well).
The goto :eof is just there to make sure only the most recent file will be opened and not all in order of date/time.
As for your space problem, surrounding the file name with quotes usually should fix that, but sometimes it's a little difficult to know where they have to be. Also, for by default tokenizes its input at spaces, that's why I included delims= in there which essentially says »Put everything into the variable and don't do any tokenizing«.

I know this is an old post, and I don't mean to revive it - I have an alternative approach to the question.
Malwarebytes' Anti-Malware includes the ability to reroute the log file to an alternate location (folder or specified file).
You can run "%programfiles%\malwarebytes' anti-malware\mbam.exe" /logtofile c:\logs\bob-mbam-log.txt. /logtofolder also works. (the above command assumes you're using a 32 bit system.)
When specifying a file, mbam appends instead of overwriting. So, that may make the log a little more difficult to parse.

Related

Delete semi duplicate files

I'm wondering if there is a way to remove semi-duplicate files (name based) using a batch file or any other means (freeware utility) in Windows?
To give an example I have following files in a directory:
fileNameXXX(aaa).ext
fileNameXXX(bbb).ext
In this case, I only want to keep the fileNameXXX(bbb).ext
it's a single line in batch:
for /f "delims=" %%f in ('dir /b "*(*).ext" ^| find /v "(ddd)"') do ECHO del "%%f"
For every file matching the filemask excluding files with (ddd) do: delete it.
Remove the ECHO if the output fits your needs.
Note: if you want to use it directly on command line (instead in a batch file), replace every %%f with %f.
Tip: think about using some more code to check, if there is a Dutch version, and if not, keep the English one (or whatever you prefer).

Batch: Preserve (creation-)date on copying files to another (flatten) folder structure, incl. renaming files to avoid doublettes

this is my first question, so I apologize beforehand if I write not as you are used to...
fact:
I've a deep folder structure with tons of files (images,videos and so on) so I want to copy that files to a flat structure for a better overview.
I want to keep (at least) the original date attributes: creation-date and last-modified date.
Problem 1) there are files with same name 00001.jpg in different folders which I want to have in same folder, so I want to add creation date/time to filename on copy process.
00001.jpg becomes 2015-11-17_11-23-35_00001.jpg
So far so good. Or not good...
Copy and XCopy doesn't give me an option to do that, without loosing at least the creation date information (I didn`t find a solution with both).
Now I try to copy the files (file by file) with robocopy to new folder and use ren on the copied file to "pre-set" the date/time information before the filename.
Here is a simple test.bat example:
setlocal enableextensions enabledelayedexpansion
robocopy . ./zzz original.txt /copy:DATSO
pause
rem :: formatted creation date of original file will be here, in real life
set "myDate=2015-11-17-_11-23-35"
rem rename "./zzz/original.txt" "!myDate!_renamed.txt" ::doesnt work: why? relative path??
rem :: this will do what I want - original creation date is kept on copy file
FOR %%A IN (zzz/original.txt) DO REN "%%~fA" "!myDate!_%%~nxA"
[possibly] Problem2) Is there a better way to do this, or could I run into thread problems (asynchronous execution). Could it be, that I try to rename a file before the robocopy has finished the copy process (e.g. for large files)?
Sorry I'm a totally batch newbie (also as poster in SO ;).
ThanX in advance for each tip and also for critics on my solution approach. Maybe I have the horse-blinkers on my head and dont see the easy solution?!
[edit: formatting of post]
[edit: content of post -> date/time in front of filename for better sorting]
It is possible to use command DIR to get recursive listed all files in the specified folder and its subfolders with creation date/time.
The format of the date/time depends on Windows Region and Language settings.
Example output for F:\Temp\Test on my machine with English Windows 7 and region is configured to Germany on running the command line dir F:\Temp\Test\* /A-D /S /TC:
Volume in drive F is TEMP
Volume Serial Number is 1911-26A4
Directory of F:\Temp\Test
25.09.2017 17:26 465.950 SimpleFile.ccl
1 File(s) 465.950 bytes
Directory of F:\Temp\Test\Test Folder
25.09.2017 17:26 360.546 Test File.tmp
1 File(s) 360.546 bytes
Total Files Listed:
2 File(s) 826.496 bytes
0 Dir(s) 58.279.460.864 bytes free
This output is filtered with findstr /R /C:"^ Directory of" /C:"^[0123][0123456789]" to get only lines starting with  Directory of (note the space at begin) or with a number in range 00 to 39.
Directory of F:\Temp\Test
25.09.2017 17:26 465.950 SimpleFile.ccl
Directory of F:\Temp\Test\Test Folder
25.09.2017 17:26 360.546 Test File.tmp
And this filtered output is processed by FOR loop and the commands executed by FOR.
#echo off
for /F "tokens=1-2*" %%A in ('dir "F:\Temp\Test\*" /A-D /S /TC ^| %SystemRoot%\System32\findstr.exe /R /C:"^ Directory of" /C:"^[0123][0123456789]" 2^>nul') do (
if "%%A %%B" == "Directory of" (
set "FilePath=%%C"
) else (
set "CreationDate=%%A"
set "CreationTime=%%B"
for /F "tokens=1*" %%I in ("%%C") do set "FileName=%%J"
call :RenameFile
)
)
goto :EOF
:RenameFile
set "NewName=%CreationDate:~-4%-%CreationDate:~3,2%-%CreationDate:~0,2%_%CreationTime:~0,2%-%CreationTime:~3,2%_%FileName%"
ren "%FilePath%\%FileName%" "%NewName%"
goto :EOF
It would be advisable to put command echo before command ren in last but one line to first verify the expected new file names.
ren "F:\Temp\Test\SimpleFile.ccl" "2017-09-25_17-26_SimpleFile.ccl"
ren "F:\Temp\Test\Test Folder\Test File.tmp" "2017-09-25_17-26_Test File.tmp"
Note: The batch file must be in a folder not processed by this batch file as otherwise the batch file itself would be renamed while running which breaks the processing of the batch file.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
dir /?
echo /?
for /?
goto /?
if /?
ren /?
set /?
By the way: WinRAR can add files into a RAR archive with creation and last access time in addition to last modification time and extract the files to a different directory with restoring also creation and last access time using SetFileTime function of Windows kernel.
currently I use Locale independent date. I use tokens from that for currrent date/time.
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetime=%%I
rem :: format it to YYYY-MM-DD_hh-mm-ss
set myDateTime=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2%_%datetime:~8,2%-%datetime:~10,2%-%datetime:~12,2%
Thats not the problem.
To clarify:
The listing is also not the problem.
I loop throw all related files without a prob (except batch files and output dir and its sub tree ;).
My problem is:
I call robocopy for each file, then I rename the file to save the original creation date. My fear is that it makes problems (Multi-Threading?) for large files and for the number of calls (many thousend times)
Is batch execution really serialized? Is the process waiting for robocopy, that it has finished, before I try to rename file. Could I run into dead-locks for vry large files? I'll test it with some fake gigabyte-files.
Your suggestion, to use winrar sounds interesting.
If I could add all that files to a big archive (with structure) and at the end extract it to target dir... I'll try it ;)
If it doesn't work I will program it in java!
There I know what to do, thats my playground :D
I thought it would be easy to write a simple batch file, to do this for me, but it seems it's not as easy as I thought!
ThanX anyway

Getting the attributes of the last modified file in a directory written in a file

I am in the need of a batch script that checks a drive (D:) for the 'last modified' attribute of *.czi files (Carl Zeiss image files) and append the data to a file on another drive. I have tried solutions with the following line:
FOR /F "delims=" %%I IN ('DIR %source%*.czi /A:-D /O:-D /T:W /B') DO COPY "%%I" > %target%
that does give me the last file, but it copies the entire file which is not that smart since they can be big. As a biologist I will spare you for my desperate attempts that did not work (spent 4-5 hours). I figure this can be done dead easily, that is if you know how... Any good suggestions? Any reply will be appreciated! Thanks in advance.
Let's assume just the last modified file time from newest file is wanted from all *.czi files in directory C:\Temp containing for example:
30.01.2017 08:13 First Listed.czi
28.01.2017 21:26 Oldest Image.czi
03.02.2017 17:13 Newest Image.czi
The batch code for this task could be:
#echo off
set "Source=C:\Temp\"
set "Target=%Source%List.txt"
for /F "delims=" %%I in ('dir "%Source%*.czi" /A:-D /B /O:-D /T:W 2^>nul') do (
echo File "%%I" last modified on %%~tI>>"%Target%"
goto AfterLoop
)
:AfterLoop
The command DIR searches in for *.czi files in directory C:\Temp and outputs the list sorted by last modification time in reverse order from newest to oldest.
In case of no *.czi file could be found, command DIR would output an error message to handle STDERR. This output message is redirected with 2>nul to device NUL to suppress it whereby the redirection operator > must be escaped here with ^ to be interpreted as redirection operator on execution of DIR command line and not already on parsing FOR command line.
%%I references the name of the file as output by DIR and %%~tI references the last modification date of the file. The help of command FOR output by running in a command prompt window for /? explains those modifiers.
The loop is exited after first output of the text redirected to the target file on which the line is appended if it is already existing because of using >> instead of just >.
For the example files list the following line is appended to C:\Temp\List.txt:
File "Newest Image.czi" last modified on 03.02.2017 17:13
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
echo /?
for /?
goto /?
set /?
See also the Microsoft article Using command redirection operators.
Your question is unclear, so let me try to rephrase it:
I think you want to find the Most Recently Modified file with a .CZI extension, and copy only that newest file to some target destination.
To list all .CZI files in all subdirectories, sorted by newest-file first:
(for /f %a in ('dir *.CZI /s /b') do #echo %~ta %~fa) | sort
If the first line of this output is the file that you want, then all you need to do is copy that one file to your target.
(and please, take the time to write detailed and clear questions so we can provide good answers)

Batch script not working due to spaces in file paths

So I'm new to batch scripting and scripting in general. I recently made a script where files from a source directory will be organised according to its 'last modified date' into a destination directory.
Here's an extract of the script:
#echo off
Setlocal EnableDelayedExpansion
echo Organise files
set /P _a="Enter source directory:"
set /P _b="Enter destination directory:"
set /P _c="Organise files by dd-mm-yyyy format (last modified)? y or n?"
if %_c% == y goto:ddmmyy
:ddmmyy
for %%A in ("%_a%\*") do echo %%~tA %%~snA %%~xA >> "%_a%\testtoken.txt"
for /F "tokens=1-7* delims=./ " %%B in (%_a%\testtoken.txt) do (
robocopy "%_a%" "%_b%\%%B-%%C-%%D" "%%G.%%H" /xf testtoken.txt /mov
)
The script works just fine unless I use directories with spaces in their names (eg. C:\Program Files instead of C:\Program). I also had the same issue with spaces in file names until I used 8.3 notation, however using 8.3 notation results in other issues like robocopy not copying files with fairly similar names (eg. TUTORI~2, TUTORI~1, TUTORI~3 etc.)
Here's the format of testtoken.txt:
02/11/2014 06:02 PM SPSETU~1 .exe
16/11/2014 09:19 AM TUTORI~4 .docx
14/11/2014 12:00 PM TUTORI~2 .docx
16/11/2014 09:19 AM TUTORI~3 .docx
14/11/2014 12:00 PM TUTORI~1 .docx
16/11/2014 09:19 AM TU44E0~1 .docx
16/11/2014 09:19 AM TU05DE~1 .docx
16/11/2014 10:59 PM UNIFYI~1 .pdf
09/11/2014 07:55 PM ZOROAS~1 .jpg
So is there a way to make the script disregard the spaces? Why won't robocopy copy files with fairly similar names in 8.3 notation and is there any way to force robocopy to actually copy the files?
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"
for %%A in ("%sourcedir%\*") do echo %%~tA %%~fA>> "%sourcedir%\testtoken.txt"
for /F "USEBACKQ tokens=1,2,3,5* delims=/ " %%B in ("%sourcedir%\testtoken.txt") do IF /i "%%~nxF" neq "testtoken.txt" (
REM method 1 - robocopy
echo(robocopy "%%~dpF." "%destdir%\%%D-%%C-%%B" "%%F" /mov
REM method 2 - XCOPY
ECHO(XCOPY "%%F" "%destdir%\%%D-%%C-%%B\"
REM method 3 - MD and move
ECHO(MD "%destdir%\%%D-%%C-%%B\"
ECHO(MOVE "%%F" "%destdir%\%%D-%%C-%%B\"
ECHO ==================================
)
GOTO :EOF
You would need to change the setting of sourcedir and destdir to suit your circumstances. I've changed the variable names to more descriptive names.
Note: I've reversed the date to yyyy-mm-dd format which sorts more easily than dd-mm-yyyy format. Simply reverse the token order %%D-%%C-%%B if you insist on dd-mm-yyyy.
I prefer method 2 or 3 over robocopy so I'm not particularly familiar with robocopy syntax. YMMV.
The required MD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MD to MD to actually create the directories. Append 2>nul to suppress error messages (eg. when the directory already exists)
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
The required XCOPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(XCOPY to XCOPY to actually copy the files.
The required ROBOCOPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(ROBOCOPY to ROBOCOPY to actually copy the files.
Obviously, choose one of the three methods.
Note that your exclusion of testtoken.txt would likely be ineffective since your code targeted short filenames and testtoken.txt is the long filename. I'm not sure that robocopy would do the exception, but the if gate I've implemented certainly will.
Since my date format and your differ, I used your data to test the procedure on my system. Obviously, it seemed to work else I'd not bother posting it.
The token-controls in the for...%%B statement re designed to allot day, month and year to %%B,C,D, skip token 4 (time) and %%E is allotted "AM/PM) - used as a dummy. %%F gets the rest of the line, which should be the full filename generated by the %%~fA into the listing file.
Edited code to remove terminal space being added to testtoken.txt lines in response to OP comment.
You probably should change the format of your file a bit. Instead of making the extension the last column just use the filename there. You then know that the last token extends to the rest of the line, including any spaces:
for /f "tokens=1-5* delims=/ " %A in ("09/11/2014 07:55 PM Test file with spaces.jpg") do (echo %F)
As for quoting any paths with spaces I don't spot any glaring issues right now. for ... in (%_a%\testtoken.txt) may be a problem, which can be solved by using
for /f "usebackq <other options>" ... in ("%_a%\testtoken.txt") do ...
at least if the documentation can be trusted:
usebackq - specifies that the new semantics are in force,
where a back quoted string is executed as a
command and a single quoted string is a
literal string command and allows the use of
double quotes to quote file names in
file-set.

Why is /F typically used with FOR loops even when dealing with non-text files?

I was looking for a batch script to identify the newest file in a directory. The examples I found all use FOR /F. When I read the help documentation on FOR, it states that /F opens, reads and processes each file.
Why is /F used in this case? I've used it with large binary files and the script does not seem to slow down so I do not think each file is actually being opened, etc.
I tried using FOR without /F to do the same job and didn't have any luck. Is there a reason for that?
For instance:
FOR %%I IN ('dir "*.AVI" /B /O:D') DO set newestAvi=%%I
does not seem to work. For some reason, newestAvi is equal to "/O:D'" at the end.
If I use
FOR /F "delims=|" %%I IN ('dir "*.AVI" /B /O:D') DO set newestAvi=%%I
then things work.
Thanks,
Dave
I think the relevant bit of the help file is
Finally, you can use the FOR /F command to parse the output of a
command. You do this by making the filenameset between the
parenthesis a back quoted string. It will be treated as a command
line, which is passed to a child CMD.EXE and the output is captured
into memory and parsed as if it was a file. So the following
example:
So, with the /F your command takes the output from
dir "*.AVI" /B /O:D
and parses each line into the command
newestAvi=%%I
which becomes
newestAvi=FileName.AVI
for each file in the current directory. The last value assigned is the one that is left at the end of the for commands execution.

Resources