certutil -hashfile : processing multiple files in a drag-dropped folder - batch-file

I'm trying to create a batch script that runs certutil -hashfile MD5 on each file in a folder and write the output to a file.
I have this code below except it only works on the files in the current folder,
I would like it to work such that when a folder is drag-dropped into the batch file .bat it processes that folder only.
for %%a in (*) do certutil -hashfile %%a MD5 >> MD5_log.txt
Also is there a way to get it to output spaces in the log file between iterations of the certutil output text?

It is actually very simple!
Simply change (*) to ("%~1\*") or other command-line arguments. If you have multiple drag-drop folders, do "%~1\*" "%~2\*", etc. Using quotes (") can prevent issue with space. So paths are now quoted. And %%a becomes %%~a, which means to de-quote.
Alternatively, you can set a variable containing all paths and process them one by one.
Result:
for %%a in ("%1\*") do certutil -hashfile "%%~a" MD5 >> MD5_log.txt

Store following file as .bat file and change testfolder and outputfile as desired.
#ECHO OFF
setlocal enabledelayedexpansion
:: Set the variables for this script.
set testfolder=C:\Test\
set outputfile=md5_files.txt
cd %testfolder%
echo > %outputfile%
for %%f in (".\*.*") do (
certutil -hashfile %%f SHA1 >>%outputfile%
echo %%ff
)
PAUSE

Related

Loop through subfolders of subfolders and execute a command on each file of the last subfolder

Consider this hierarchy:
MainFolder\Sub_Folder1\Original_Files\
\Converted_Files\
\Sub_Folder2\Original_Files\
\Converted_Files\
Now in each ...\Original_Files\ I've a bunch of video files which I'll encode and save to the respective ...\Converted_Files\.
I could do it for one subfolder with this batch code:
#echo off
set "sourcedir=G:\Animation\Anime\OnePiece\Episodes\Main"
set "outputdir=G:\Animation\Anime\OnePiece\Episodes\Converted"
PUSHD "%sourcedir%"
for %%F in (*.mkv) DO ffmpeg -i "%%F" -s 640x480 -map 0 -c:v libx265 "%outputdir%\%%F"
POPD
I've generated a text file with the folder paths of all the subfolders which contains:
G:\Animation\ToConvert\Berserk_1997_The_Complete_Series
G:\Animation\ToConvert\Blue_Exorcist
G:\Animation\ToConvert\Elfen_Lied
Every folder listed in the file has Main and Converted folders within them. I've to loop through all files in Main and save into Converted as you might see in above.
This is something I came up with :
#echo off
for /F "tokens=*" %%A in (f.txt) DO (
set "sourcedir=%A%\Main"
set "outputdir=%A%\Converted"
PUSHD "%sourcedir%"
for %%F in (*.mkv) DO ffmpeg -i "%%F" -s 640x480 -map 0 -c:v libx265 "%outputdir%\%%F"
POPD
) %%A
Running for /F "tokens=*" %A in (f.txt) DO #echo %A gives me the names of the subfolders.
I thought somehow if I could pass the name to some variable and concatenate \Main and \Converted to it, it might work.
But on running the code above from within a command prompt window, it's just switching the current directory from the folder I'm running the batch file to C:\Windows.
How can I run nested loops, one for the subfolders and then chose between working in Main and saving in Converted and the next loop for files in Main?
Your last batch code fails because of
referencing the loop variable A like an environment variable with %A% instead of %%A and
referencing environment variables defined/set within a command block defined with ( and ) requires the usage of delayed expansion enabled before with the command line setlocal EnableDelayedExpansion and using !sourcedir! and !outputdir! instead of %sourcedir% and %outputdir% which are already replaced by current value of the environment variables sourcedir and outputdir (empty string here as not defined before) when Windows command processor parses the entire command block before executing command FOR the first time.
%%A after closing parenthesis at end is unknown for Windows command interpreter and results therefore in an exit of batch processing because of a syntax error.
However, better than your code which requires first the creation of a text file with the folder paths would be the usage of following code:
#echo off
for /D %%D in ("G:\Animation\ToConvert\*") do (
if exist "%%D\Main\*.mkv" (
echo Processing %%D ...
if not exist "%%D\Converted\*" md "%%D\Converted"
for %%I in ("%%D\Main\*.mkv") do (
ffmpeg.exe -i "%%I" -s 640x480 -map 0 -c:v libx265 "%%D\Converted\%%~nxI"
)
)
)
The outer FOR with parameter /D finds just non hidden subfolders within folder G:\Animation\ToConvert and holds in loop variable D the name of the subfolder with full path not ending with a backslash.
The IF condition checks if in the current subfolder there is a folder Main with 1 or more *.mkv files to process. If this condition is true,
an information message is output to see progress on running the batch file,
in current subfolder the folder Converted is created if not already existing,
another FOR loop is executed to process each *.mkv file found in the folder Main of current subfolder.
The loop variable I holds the name of the current *.mkv file with full path. So "%%I" can be used for the input file as current directory does not matter because input file name is with full path.
For the output file the folder Converted in current subfolder is specified and appended is with %%~nxI the file name and the file extension of input file as name for the output file.
This batch code does not require delayed expansion as there is no environment variable used, only the loop variables D and I.
For completeness also your code using a text file containing line by line the folders to process with removing all unnecessary environment variables to make it possible to run the batch file without using the commands setlocal and endlocal.
#echo off
for /F "usebackq tokens=*" %%A in ("f.txt") do (
if exist "%%A\Main\*.mkv" (
echo Processing %%A ...
if not exist "%%A\Converted\*" md "%%A\Converted"
for %%I in ("%%A\Main\*.mkv") do (
ffmpeg.exe -i "%%I" -s 640x480 -map 0 -c:v libx265 "%%A\Converted\%%~nxI"
)
)
)
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.
echo /?
for /?
if /?
md /?
BTW: See this answer and the other answers linked there if you ever want to understand what delayed expansion is and what the commands setlocal and endlocal do not needed here.
#Mofi wrote a great answer, both his codes work flawlessly. This is just a simpler version I am running because the conditions being checked in that program are already met.
#echo off
for /F "tokens=*" %%A in (f.txt) DO (
for %%F in (%%A\Main\*.mkv) DO ffmpeg -i "%%F" -s 640x480 -map 0 -c:v libx265 "%%A\Converted\%%~nxF"
)

How to compress each subfolder in a folder into a separate RAR archive using WinRAR?

I am really new to batch file coding and need your help.
I've these directories:
c:\rar\temp1\xy.jpg
c:\rar\temp1\sd.jpg
c:\rar\temp1\dd.jpg
c:\rar\temp2\ss.jpg
c:\rar\temp2\aa.jpg
c:\rar\temp2\sd.jpg
c:\rar\temp3\pp.jpg
c:\rar\temp3\ll.jpg
c:\rar\temp3\kk.jpg
And I want to compress them to this
c:\rar\temp1\temp1.rar
c:\rar\temp2\temp2.rar
c:\rar\temp3\temp3.rar
How could this be done using WinRAR?
This can be done also with WinRAR without using a batch file, not exactly as requested, but similar to what is wanted.
Start WinRAR and navigate to folder c:\rar\.
Select the folders temp1, temp2 and temp3 and click on button Add in the toolbar.
As archive name specify now the folder for the RAR archives, for example c:\rar\.
Switch to tab Files and check there the option Put each file to separate archive.
Click on button OK.
WinRAR creates now three RAR archives with the file names temp1.rar, temp2.rar and temp3.rar in folder c:\rar\ with each archive containing the appropriate folder with all files and subfolders.
The list of files to add can be changed also on tab Files by entering for example *.txt in Files to exclude to ignore text files in the three folders on creating the archives.
And finally it makes sense to enter *.jpg on tab Files in edit field below Files to store without compression as JPEG files usually contain already compressed data and therefore WinRAR cannot really compress the data of the files further.
Here is also a batch file solution to move the files in all non-hidden subfolders of c:\rar\ and their subfolders into an archive file with name of the subfolder created in each subfolder as requested.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "RAREXE=Rar.exe"
if exist "%RAREXE%" goto CreateArchives
if exist "%ProgramFiles%\WinRAR\Rar.exe" set "RAREXE=%ProgramFiles%\WinRAR\Rar.exe" & goto CreateArchives
if exist "%ProgramFiles(x86)%\WinRAR\Rar.exe" set "RAREXE=%ProgramFiles(x86)%\WinRAR\Rar.exe" & goto CreateArchives
for /F "skip=2 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe query "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe" /v Path 2^>nul') do (
if /I "%%I" == "Path" if exist "%%~K\Rar.exe" for %%L in ("%%~K\Rar.exe") do set "RAREXE=%%~fL" & goto CreateArchives
)
for /F "skip=2 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe query "HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe" /v Path 2^>nul') do (
if /I "%%I" == "Path" if exist "%%~K\Rar.exe" for %%L in ("%%~K\Rar.exe") do set "RAREXE=%%~fL" & goto CreateArchives
)
for /F "delims=" %%I in ('%SystemRoot%\System32\where.exe Rar.exe 2^>nul') do set "RAREXE=%%I" & goto CreateArchives
echo ERROR: Could not find Rar.exe!
echo/
echo Please define the variable RAREXE at top of the batch file
echo "%~f0"
echo with the full qualified file name of the executable Rar.exe.
echo/
pause
goto :EOF
:CreateArchives
set "Error="
for /D %%I in ("c:\rar\*") do (
echo Creating RAR archive for "%%I" ...
"%RAREXE%" m -# -cfg- -ep1 -idq -m3 -msgif;png;jpg;rar;zip -r -s- -tl -y -- "%%I\%%~nxI.rar" "%%I\"
if errorlevel 1 set "Error=1"
)
if defined Error echo/& pause
endlocal
The lines after set "RAREXE=Rar.exe" up to :CreateArchives can be omitted on definition of environment variable RAREXE with correct full qualified file name.
Please read the text file Rar.txt in the WinRAR program files folder for an explanation of RAR command m and the used switches. The question does not contain any information with which options the RAR archives should be created at all.
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 /? ... explains %~f0 ... full name of batch file
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
set /?
setlocal /?
where /?
See also single line with multiple commands using Windows batch file for an explanation of the operator &.
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on the three FOR command lines to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded reg or where command line with using a separate command process started in background.
This script can work as well:
#echo off
for %%a in ("C:\rar\temp1" "C:\rar\temp2" "C:\rar\temp3") do (
pushd "%%~a"
"C:\Program Files\WinRAR\rar.exe" a -r temp.rar *
popd
)
In Python v3.x:
Tested on Python v3.7
Tested on Windows 10 x64
import os
# NOTE: Script is disabled by default, uncomment final line to run for real.
base_dir = "E:\target_dir"
# base_dir = os.getcwd() # Uncomment this to run on the directory the script is in.
# Stage 1: Get list of directories to compress. Top level only.
sub_dirs_raw = [os.path.join(base_dir, o) for o in os.listdir(base_dir) if os.path.isdir(os.path.join(base_dir, o))]
# Stage 2: Allow us exclude directories we do not want (can omit this entire section if we wish).
dirs = []
for d in sub_dirs_raw:
if "legacy" in d or "legacy_old" in d:
continue # Skip unwanted directories
print(d)
dirs.append(d)
# Stage 3: Compress directories into .rar files.
for d in dirs:
os.chdir(d) # Change to target directory.
# Also adds 3% recovery record using "-rr3" switch.
cmd = f"\"C:\Program Files\\WinRAR\\rar.exe\" a -rr3 -r {d}.rar *"
print(cmd)
# Script is disabled by default, uncomment this next line to execute the command.
# os.system(cmd)
Notes:
Script will do nothing but print commands, unless the final line os.system(cmd) is uncommented by removing the leading # .
Run the script, it will print out the DOS commands that it will execute. When you are happy with the results, uncomment final line to run it for real.
Example: if there was a directory containing three folders mydir1, mydir2, mydir3, it would create three .rar files: mydir1.rar, mydir2.rar, mydir3.rar.
This demo code will skip directories with "legacy" and "legacy_old" in the name. You can update to add your own directories to skip.
To execute the script, install Python 3.x, paste the lines above into script.py, then run the DOS command python script.py from any directory. Set the target directory using the second line. Alternatively, run the script using PyCharm.
This should work it also checks if the files were compressed alright.
You may need to change this part "cd Program Files\WinRAR" depending on where winrar is installed.
#echo Off
Cd\
cd Program Files\WinRAR
rar a -r c:\rar\temp1\temp1.rar c:\rar\temp1\*.jpg c:\rar\temp1\
if "%ERRORLEVEL%"=="0" ( Echo Files compressed
) Else Echo Failed
rar a -r c:\rar\temp2\temp2.rar c:\rar\temp2\*.jpg c:\rar\temp2\
if "%ERRORLEVEL%"=="0" ( Echo Files compressed
) Else Echo Failed
rar a -r c:\rar\temp3\temp3.rar c:\rar\temp3\*.jpg c:\rar\temp3\
if "%ERRORLEVEL%"=="0" ( Echo Files compressed
) Else Echo Failed
Pause
Below Script will compress each folder as a RAR file within the current directory with very useful info while compressing a large size of data.
#echo off
#for /D %%I in (".\*") do echo started at %date% %time% compressing... "%%I" && #"%ProgramFiles%\WinRAR\Rar.exe" a -cfg- -ep1 -inul -m5 -r -- "%%I.rar" "%%I\"
echo "Completed Successfully !!!"
pause

Reading input from a file doesn't work for filenames containing spaces

I have a case where I have to move over 15,000 files. There are many duplicates, so I parsed them by MD5 and now I have a list of file names in an input file (files.txt).
I want to read from it, then copy the listed files to a new directory.
I pulled an old batch that someone had written as a two-part simple script and modified it.
It works for files without spaces. How can I get this to cover all file names?
Also, can't I put all of this into one file?
Cstart.bat:
for /f %%x in (files.txt) do call copyfiles.bat
copyfiles.bat:
set filename=%1
copy "C:\temp\%filename%" "C:\temp\pruned files\"
Your current code doesn't even pass the filename to copyfiles.bat, so it's not working with or without spaces. (If you need to confirm that, add echo %1 %filename & pause before the copy line in copyfiles.bat and run cstart.bat.)
With that being said, you can do it all in one file easily:
for /f %%x "tokens=1 delims=*" in (files.txt) do copy "C:\Temp\%%x" "C:\Temp\pruned files\%%x"
To make sure it works, just replace the copy in the line above with echo and run it from a command prompt.
I tested this with a text file named test.txt that contained the following:
One.txt
Two.txt
Three.txt
And Four.txt
with a batch file named testcopy.bat containing this:
#echo off
for /f "tokens=1 delims=*" %%x in (test.txt) do echo "C:\Temp\%%x" "C:\Temp\test this\%%x"
The above test showed this output:
e:\TempFiles>testcopy
"C:\Temp\One.txt" "C:\Temp\test this\One.txt"
"C:\Temp\Two.txt" "C:\Temp\test this\Two.txt"
"C:\Temp\Three.txt" "C:\Temp\test this\Three.txt"
"C:\Temp\And Four.txt" "C:\Temp\test this\And Four.txt"
for /f "usebackqdelims=" %%x in ("my file list.txt") do copy "C:\temp\%%~x" "C:\temp\pruned files"

I need a batch file to change one line of text in one directory to the same text file in a different directory

Basically, I have a text file with one line of text SetNumber=01 in 5 folders
C:\Documents and Settings\User\Desktop\Test\test.txt
C:\Folder\Test\test.txt
C:\Test\test.txt
etc.
I need to change this SetNumber=01 to different numbers monthly, for instance SetNumber=01 to SetNumber=02, in all these folders, and would like to run a batch file that would copy and replace this line of text from
C:\Documents and Settings\User\Desktop\Test\test.txt
into
C:Folder\Test\test.txt.
etc.
Any help would be greatly appreciated!!
OK, here we go. This copies the file C:\Documents and Settings\User\Desktop\Test\test.txt to all ..\test\test.txt files on the current volume (they were erased). Remove the echo command, if the output is OK:
#echo off&setlocal enabledelayedexpansion
set "sourcefile=C:\Documents and Settings\User\Desktop\Test\test.txt"
for /f "delims=" %%i in ('dir /s /b /a-d \test.txt') do (
set "fpath=%%~fi"
if "!fpath:*test\test.txt=!"=="" if not "%sourcefile%"=="%%~fi" (
echo copy "%sourcefile%" "%%~fi"
)
)
The Batch file below change all files named test.txt in any folder in the disk by inserting this line "SetNumber=%1":
#echo off
for /R \ %%a in (test.txt) do echo SetNumber=%1> "%%a"
For example, if previous Batch file is called SetNumber.bat, you may change all the files to SetNumber=02 with this command:
setnumber=02
Antonio

Assistance with coding change in Windows batch script?

I have a batch script which unzip and renames each file.
Unfortunately I now need to keep the filename of the zip file it came from.
Example Jazz1.zip now unzips and the outcoming text file becomes 1.Jazz1.zip.txt.
So I want %%F to become %%F - 4- characters.
Unfortunately I want it to be Jazz1.txt.
::Setup the stage...
SETLOCAL ENABLEDELAYEDEXPANSION
SET folder=C:\P\DataSource2_W
SET count=1
::Action
CD "%folder%"
FOR %%F IN ("*.zip") DO (
"C:\Program Files (x86)\WinZip\wzunzip" %%F
MOVE *.txt "C:\P\DataSource2_W\TextFiles\!count!%%F.txt"
SET /a count=!count!+1
)
ENDLOCAL
I do not understand what you are trying to do with the COUNT variable, nor do I understand how you are handling a ZIP file with multiple .TXT files.
But I do understand that you want the base name of each ZIP file, (name without the extension). That is easy - simply use the ~n modifier (type HELP FOR from the command prompt for more info).
So if %%F = Jazz1.zip, then %%~nF yields Jazz1

Resources