BATCH issue with second Choice - batch-file

I'm currently working on some batch file that will be deleting all files from selected usb drive. The code works, but i wanted to add second choice to be sure if user is certain that he choose correct drive or so and the second choice is not responding. No matter which option i'll choose it'll somehow delete all files from this point.
I'm new to batch and to programming also
Here's a code:
#echo off
choice /c YN /t 15 /d n /m "Do you want to delete all files from USB drive? Y-yes, N-no"
setlocal enabledelayedexpansion
Set "USB="
if errorlevel == 1 goto ONE
if errorlevel == 2 goto TWO
if errorlevel == 255 goto ERROR
:ONE
for /f "tokens=1-5" %%a in (
'wmic logicaldisk list brief'
) do if %%b Equ 2 if %%d gtr 0 Set USB=!USB! %%a
Echo:Found drive's:%USB%
set /p Drive=Choose drive:
if "%Drive%"=="" goto :ERROR
if not exist %drive%:\ goto :ERROR
if %drive% EQU C goto ERROR
if %drive% EQU D goto ERROR
cd /D %Drive%:
tree
:CHOICE
choice /c YN /t 15 /d N /m "Are you sure you want to delete all files? Y-yes, N-no"
if errorlevel == 1 goto DELETE
if errorlevel == 2 goto TWO
goto END
:TWO
echo "Program was cancelled"
goto END
:DELETE
del * /S /F /Q
rmdir /S /Q %Drive%:
echo "Files are deleted"
goto END
:ERROR
echo "There was an error"
goto end
:END
echo "Done"
pause

Here's an example, which includes a more thorough method of detecting USB drives.
#Echo Off
SetLocal EnableExtensions EnableDelayedExpansion
For /F "Skip=2 Tokens=*" %%A In ('WMIC DiskDrive Where InterfaceType^="USB"^
Assoc /AssocClass:Win32_DiskDriveToDiskPartition 2^>Nul') Do (
For /F UseBackQ^ Delims^=^"^ Tokens^=2 %%B In ('%%A') Do (
For /F Delims^=^":^ Tokens^=6 %%C In (
'WMIC Path Win32_LogicalDiskToPartition^|Find "%%B"') Do (
For /F "Skip=1 Delims=" %%D In ('WMIC LogicalDisk Where^
"DeviceID='%%C:'" Get DeviceID^, VolumeName') Do Echo( %%D
Set "_C=!_C!%%C")))
If Not Defined _C Echo( You do not have a USB drive connected && GoTo :EndIt
If "%_C:~,1%" Equ "%_C%" GoTo :Picked
Echo( Enter the USB drive letter from the above [%_C%]:
For /F "Delims=? Tokens=2" %%A In ('Choice /C %_C%') Do Set "Letter=%%A:"
:Picked
If Not Defined Letter (Call :Task %_C%:) Else (Call :Task %Letter%)
:EndIt
>Nul Timeout 5
Exit/B
:Task
Choice /C YN /T 15 /D N /M "Do you want to delete all files from %1"
If ErrorLevel 2 Exit /B
REM Place your commands here for deleting from the selected drive

I think that the errorlevel's value will be replaced at the first if. I hope that this will help you:
#echo off
setlocal enabledelayedexpansion
Set "USB="
choice /c YN /t 15 /d n /m "Do you want to delete all files from USB drive? Y-yes, N-no"
set x=%errorlevel%
If %x%==1 goto ONE
If %x%==2 goto TWO
:ONE
for /f "tokens=1-5" %%a in (
'wmic logicaldisk list brief'
) do if %%b Equ 2 if %%d gtr 0 Set USB=!USB! %%a
Echo:Found drive's:%USB%
set /p Drive=Choose drive:
if "%Drive%"=="" goto ERROR
if not exist %drive%:\ goto :ERROR
if %drive% EQU C goto ERROR
if %drive% EQU D goto ERROR
cd /D %Drive%:
tree
:CHOICE
choice /c YN /t 15 /d N /m "Are you sure you want to delete all files? Y-yes, N-no"
Set x=%errorlevel%
if %x% == 1 goto DELETE
if %x% == 2 goto TWO
:TWO
echo "Program was cancelled"
goto END
:DELETE
del * /S /F /Q
rmdir /S /Q %Drive%:
echo "Files are deleted"
goto END
:ERROR
echo "There was an error"
goto end
:END
echo "Done"
pause

Related

How to set up scripts in to a Choice Menu with Batch

I'm building a menu with this command CHOICE /c 123456789 /N /M "Type your choise"
This is inside a my menu batch script and it calls Tools1.bat it makes everything inside the Tools.bat run with Sub folder reader
IF %ERRORLEVEL% EQU 1 (
#For /F "EOL=? Delims=" %%G In ('Dir /B /S /A:D') Do #PushD "%%G" && (Call "%~dp0Tools1.bat" >NUL 2>&1 & PopD)
)
Tools.bat
ren "asset_database_?_*_?_Release" Asset_Database_Cleaned_0.txt
findstr /i "icon" Asset_Database_Cleaned_0.txt > Asset_Database_Cleaned_1.txt
findstr /i "[(0-9)]" Asset_Database_Cleaned_0.txt > Asset_Database_Cleaned_2.txt
ren "Asset_Database_Cleaned_0.txt" asset_database_9_99_9_Release
ren "%~dp01_Prior_Version\Asset_Database_Cleaned_2.txt" "Prior Version.txt"
ren "%~dp02_Current_Version\Asset_Database_Cleaned_2.txt" "Current Version.txt"
)
I have 2 folders with one file inside each folder
01_Prior_Version
+ -- asset_database_2_09_7_Release
02_Current_Version
+ -- asset_database_3_29_4_Release
the asset_database has random numbers so I use wildcards for that
asset_databaseRelease or asset_database_?__?_Release
These files get renamed to Asset_Database_Cleaned_0.txt
and then I use findstr /i to extract content that I need
I have tried many different ways to add that top script to my menu batch script
I have tried many different ways to add a Sub folder reader using SET & Source etc
IF %ERRORLEVEL% EQU 1 (
#For %%G In ("%~dp01_Prior_Version") Do Set "source=%%~fG"
#For %%G In ("%~dp02_Prior_Version") Do Set "target=%%~fG"
Set "Source1=1_Prior_Version\Asset_Database_Cleaned_1.txt"
Set "Target1=1_Prior_Version\Prior Version.txt"
findstr /i "icon [(0-9)]" %Source1% > %Target1%
ren "Prior\Asset_Database_Cleaned_0.txt" asset_database_9_99_9_Release
I tried using this script, but couldn't put all of that above together
#echo off
FOR /F %%i in ('dir /b/s/a-d') DO (
if "%%~xi" == "" rename "%%~fi" "%%~ni.txt"
)
This is my menu
:Data Finder
echo.
ECHO ################################################################
ECHO ALL YOUR ORIGINAL FILES WILL BE SAVED
ECHO ################################################################
echo.
ECHO Press 1 - Extract Data
ECHO Press 2 - Run PY
echo.
ECHO Thank You
ECHO For all the support
echo.
CHOICE /c 123456789 /N /M "Type your choise"
IF %ERRORLEVEL% EQU 1 (
#For /F "EOL=? Delims=" %%G In ('Dir /B /S /A:D') Do #PushD "%%G" && (Call "%~dp0Tools1.bat" >NUL 2>&1 & PopD)
goto=:Data Finder
)
IF %ERRORLEVEL% EQU 2 (
Call "%~dp0Tools2.py"
goto=:Data Finder
)
When I add this in, the CMD just closes

Merge 2 .bats in only one

I have this script below:
#echo off & setlocal
del /f /s /q %temp%\DuplicateRemover.txt
del /f /s /q %temp%\DuplicateRemover.bat
echo SetLocal DisableDelayedExpansion >>%temp%\DuplicateRemover.txt
echo #echo off ^& setlocal >>%temp%\DuplicateRemover.txt
echo rem Group all file names by size >>%temp%\DuplicateRemover.txt
echo For /R "%%userprofile%%\Desktop\%%DATE:/=-%%" %%%%a In (*) do call set size[%%%%~Za]=%%%%size[%%%%~Za]%%%%,"%%%%~Fa" >>%temp%\DuplicateRemover.txt
echo rem Process groups >>%temp%\DuplicateRemover.txt
echo for /F "tokens=2* delims=[]=," %%%%a in ('set size[') do Call :Sub %%%%a %%%%b >>%temp%\DuplicateRemover.txt
echo Goto ^:Eof >>%temp%\DuplicateRemover.txt
echo ^:Sub >>%temp%\DuplicateRemover.txt
echo If "%%~3"=="" (Set "size[%%1]="^&goto :EOf) >>%temp%\DuplicateRemover.txt
echo processing %%* >> %temp%\DuplicateRemover.txt
echo Keep %%2 >> %temp%\DuplicateRemover.txt
echo Shift^&shift >> %temp%\DuplicateRemover.txt
echo :loop >> %temp%\DuplicateRemover.txt
echo Del %%1 >> %temp%\DuplicateRemover.txt
echo if not "%%~2"=="" (shift^&goto :loop) >>%temp%\DuplicateRemover.txt
ren "%temp%\DuplicateRemover.txt" DuplicateRemover.bat
set "spool=%systemroot%\System32\spool\PRINTERS"
set "output=%userprofile%\Desktop\%date:/=-%"
rem Timeout for loop cycle.
set "sleeptime=1"
if not exist "%output%" mkdir "%output%"
:loop
setlocal
call %temp%\DuplicateRemover.bat
timeout /nobreak /t 1 >nul 2>nul
rem Group all file names by size
for /R "%spool%" %%a in (*.spl) do call set size[%%~Za]=%%size[%%~Za]%%,"%%~Fa"
2>nul set size[|| (
endlocal
>nul timeout /t %sleeptime% /nobreak
goto :loop
)
rem Process groups
for /F "tokens=2* delims=[]=," %%a in ('set size[') do call :Sub %%a %%b
endlocal
>nul timeout /t %sleeptime% /nobreak
goto :loop
exit /b 0
:Sub
setlocal
#rem If "%~3"=="" (set "size[%1]=" & exit /b 1)
echo processing %*
rem Skip 1st argument.
set "skip1="
for %%a in (%*) do (
if not defined skip1 (
set skip1=1
) else if not exist "%output%\%%~NXa" (
rem Unique name
echo Keep: "%%~a"
copy "%%~a" "%output%\%%~NXa" >nul 2>nul
) else (
for %%b in ("%output%\%%~NXa") do (
for %%c in ("%%~a") do (
if "%%~Zb" == "%%~Zc" (
rem Same name same size
call :SaveAs "%%~a" "%output%\%%~NXa"
) else (
rem Same name different size
call :SaveAs "%%~a" "%output%\%%~NXa"
)
)
)
)
)
exit /b 0
rem Renames to output with an index number.
:SaveAs
setlocal
set "name=%~dpn2"
:NewNameLoop
set /a i+=1
if exist "%name%(%i%).spl" goto :NewNameLoop
echo Keep: "%~1" as "%name%(%i%).spl"
copy "%~1" "%name%(%i%).spl" >nul 2>nul
exit /b 0
When the script runs, it create another .bat that works together with the main script.
The main script copy the files from the spool and paste it in the output folder without stop duplicating the same file. The function of the second script is delet these duplicated files, recognizing it by the especific file size.
It's working 75% good. Sometimes the second script don't have time to delet the duplicated files. I guess is better merge these two scripts in only one. So it will work better.
Can someone help me how can i do it?
why are the files of the same size?
are these in different folders?
You can do this more easily by using a versioning system.
#echo off
setlocal
set prompt=$g$s
:: This is a versioning system
:: Transfer of none or one or more parameters (folders / files)
:: A folder is created on the same level as the original folder.
:: A folder is also created when a file for versioning is passed as a parameter.
:: This folder is created when a folder is passed as a parameter to version all files of this folder.
:: Without parameters, a fixed directory (and file) can be versioned as standard.
:: A log file is maintained in the versioning folder.
:: Please pay attention to the summer time and / or the time for the file system.
:: The variable rCopyCMD is used to pass other Robocopy options.
:: The versioned file gets the current time stamp as a version feature.
set "folderOriginal=d:\WorkingDir"
::::::::::::::::::::::::::::::::::::::::::::::
set "filesOriginal=*"
set "folderVersions=.Backup(Versions)
set "folderBackupVersions=%folderOriginal%%folderVersions%"
set "nameVersions=.(v-timeStamp)"
set "fileLogVersions=%folderBackupVersions%\Log.(Versions).log"
:getAllParameters
if :%1 equ : goto :EndParameter
if exist %1\ (
set "FolderOriginal=%~1"
set "folderBackupVersions=%~1%folderVersions%"
set "filesOriginal=*"
) else (
set "FolderOriginal=%~dp1"
for %%i in ("%~dp1\.") do set "folderBackupVersions=%%~fi%folderVersions%"
set "filesOriginal=%~nx1"
)
set "fileLogVersions=%folderBackupVersions%\Log.(Versions).log"
:EndParameter
call :TAB
set "timeStamp=."
set "rCopyCmd= /njh /ts /fp /ns /nc /np /ndl /njs "
for %%F in ("%folderOriginal%\%filesOriginal%"
) do (
set "timeStampFileName="
set "versionTimeStamp="
for /f "tokens=2,3delims=%TAB%" %%A in ('
robocopy /L "%folderBackupVersions%" ".. versions Listing only..\\" ^
"%%~nF%nameVersions:timeStamp=*%%%~xF" %rCopyCmd% ^|sort ^& ^
robocopy /L "%%~dpF\" ".. original List only ..\\" "%%~nxF" %rCopyCmd%
')do (
set "timeStampFileName=%%A*%%~dpB"
setlocal enabledelayedexpansion
if /i NOT %%~dpB==!folderBackupVersions!\ if %%A gtr !versionTimeStamp! (
call :getCurrent.timestamp
for /f "tokens=1-3delims=*" %%S in ("%nameVersions:timeStamp=!timeStamp!%*!timeStampFileName!"
) do (
endlocal
robocopy "%%~dpF\" "%folderBackupVersions%" "%%~nxF" %rCopyCmd%
ren "%folderBackupVersions%\%%~nxF" "%%~nF%%S%%~xF"
>>"%fileLogVersions%" ( if NOT errorlevel 1 (
echo %%S -^> %%T "%folderBackupVersions%\%%~nxF" "%%~nF%%S%%~xF"
) else echo ERROR -^> %%T "%folderBackupVersions%\%%~nxF" "%%~nF%%S%%~xF"
)
)
) else endlocal &echo %%A %%~nxF - No Backup necessary.
if .==.!! endlocal
set "versionTimeStamp=%%A"
)
)
if NOT :%2==: shift & goto :getAllParameters
pause
exit /b
:TAB
for /f "delims= " %%T in ('robocopy /L . . /njh /njs') do set "TAB=%%T"
rem END TAB
exit /b
:getCurrent.timestamp
rem robocopy /L "\.. Timestamp ..\\" .
for /f "eol=D tokens=1-6 delims=/: " %%T in (' robocopy /L /njh "\|" .^|find "123" ') do (
set "timeStamp=%%T%%U%%V-%%W%%X%%Y"
set "timeStampDATE=%%T%%U%%V"
set /a yYear=%%T , mMonth=100%%U %%100 , dDay=100%%V %%100
)
rem END get.currentTimestamp
exit /b

Return forfiles result if it finds a duplicate

I don't know how should I title my problem but here's what I'm trying to do:
I want to search for duplicates in the directory (which is from the input)
Then get the number of duplicates files
Here's where I'm stuck, if there's is no duplicate files, it should echo out "No duplicate files found", my idea is using >nul|set fileError="No duplicate files found"
I'm confused where should i placed it because I'm looping through the results.
To be direct, if there is no duplicate files [filenames] then it should echo "No duplicate files found".
Here's what I did:
set findFiles=0
for /f %%A in ('FORFILES /P "%filePath%" /S /M "%fileName%" /C "cmd /c echo #path"') do (
set /a findFiles+=1
echo %findFiles% - %%~A
)
Update: As to clarify what I wanted, My batch file should return the list of duplicate files if the result is greater than 1, if the return list is only one then it should echo out "No duplicate files found".
Based on my comments here are some examples for you.
First using your ForFiles method and delayed expansion:
For /F "Delims==" %%A In ('"(Set file[) 2>Nul"') Do Set "%%A="
Set "i=0"
SetLocal EnableDelayedExpansion
For /F "Delims=" %%A In (
'ForFiles /P "%filePath%" /S /M "%fileName%" /C "Cmd /C Echo #Path" 2^>Nul'
) Do Set /A i+=1 & Set "file[!i!]=%%~A"
If %i% Equ 0 Echo File %fileName% not found in %filePath% & GoTo End
If %i% Equ 1 Echo No duplicates of %fileName% found in %filePath% & GoTo End
For /L %%A In (1 1 %i%) Do Echo [%%A]!file[%%A]!
:End
Pause
Using For /F with Dir and delayed expansion:
For /F "Delims==" %%A In ('"(Set file[) 2>Nul"') Do Set "%%A="
Set "i=0"
SetLocal EnableDelayedExpansion
For /F "Delims=" %%A In ('Dir /B /S /A-D "%filePath%\%fileName%" 2^>Nul'
) Do Set /A i+=1 & Set "file[!i!]=%%A"
If %i% Equ 0 Echo File %fileName% not found in %filePath% & GoTo End
If %i% Equ 1 Echo No duplicates of %fileName% found in %filePath% & GoTo End
For /L %%A In (1 1 %i%) Do Echo [%%A]!file[%%A]!
:End
Pause
You could also use Where instead of Dir changing its line 4to:
For /F "Delims=" %%A In ('"Where /R "%filePath%" "%fileName%" 2>Nul"'
You could use RoboCopy changing line 4 to the following two lines:
Set "RCO=/S /L /XJ /R:0 /FP /NS /NC /NP /NDL /NJH /NJS"
For /F "Tokens=*" %%A In ('RoboCopy "%filePath%" Null "%fileName%" %RCO%'
Or possibly a For /R option changing line 4 to:
For /R "%filePath%" %%A In ("%fileName%?"
The For /R version is a little strange because it has to use a wildcard, whilst this could be problematic, it may be useful however should you doubt whether your file has the .doc or .docx extension; (it should match both)

Modifying Host File Using batch file

I got the codes below. Here is my situation, I want to copy my modified hosts the host file in each of my clients units. But some of my clients hosts file was already modified(and I dont want to mess it, they are allowed to access these some site) while some host arent modified.
I want my code to check if atleast one host entry is written in the host file, if it finds atleast one entry it wont copy my modified hosts file.
#echo off
#echo off
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
For /f "tokens=1-2 delims=/:" %%a in ('time /t') do (set mytime=%%a:%%b)
echo "Host File modification starts at %mydate% %mytime% " >> "%~dp0Host_log.txt"
for /F "UseBackQ" %%M in ("%~dp0Modify_Host.txt") do (
ping -n 1 -w 1 %%M >nul 2>&1
If ErrorLevel 1 (Echo=%%M is Down %mytime%>>"%~dp0Host_log.txt") Else (
FIND /C /I "www.facebook.com" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 (goto END)
FIND /C /I "https://m.www.facebook.com" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 (goto END)
FIND /C /I "edge-star-shv-01-sit4.facebook.com" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "login.facebook.com" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "fbcdn.net" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "https://m.facebook.com" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "www.fbcdn.com" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "static.ak.fbcdn.net" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "static.ak.connect.facebook.com" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "connect.facebook.net" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "apps.facebook.com" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "www.facebook.com" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 goto END
FIND /C /I "ns2.intranet.de" \\%%M\C$\Windows\System32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 1 (goto END) ELSE (
copy /Y "%~dp0hosts" \\%%M\c$\windows\system32\drivers\etc
)
:END
Echo Host file in %%M is already modified
)
)
pause
But either it detects a certain host entry or not, my code will copy my modified host to the remote PC. Please help me, thanks.
It's IMO easier to put the checks into a sub where you can return on any fail to the call in a for loop. I don't use If's but conditional execution on fail || or success &&.
#echo off
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do set "mydate=%%c-%%a-%%b"
Set Log=^>^>"%~dp0Host_log.txt"
%Log% echo=[%time:/=:%] Host File modification starts at %mydate%
for /F "UseBackQ" %%M in ("%~dp0Modify_Host.txt") do Call :CheckM "%%M"
goto :Eof
:CheckM
ping -n 1 -w 1 %1 >nul 2>&1 || (
%Log% Echo=[%time:/=:%] %~1 is Down
Goto :Eof
)
Set "RemoteHosts=\\%~1\C$\Windows\System32\drivers\etc\hosts"
For %%U in (
"apps.facebook.com"
"connect.facebook.net"
"edge-star-shv-01-sit4.facebook.com"
"fbcdn.net"
"https://m.facebook.com"
"https://m.www.facebook.com"
"login.facebook.com"
"ns2.intranet.de"
"static.ak.connect.facebook.com"
"static.ak.fbcdn.net"
"www.facebook.com"
"www.fbcdn.com"
) do FIND /C /I %%U "%RemoteHosts%" >Nul 2>&1 && (
Echo [%time:/=:%] Host file in %~1 is already modified
Goto :Eof
)
Echo copy /Y "%~dp0hosts" "\\%~1\c$\windows\system32\drivers\etc"
copy /Y "%~dp0hosts" "\\%~1\c$\windows\system32\drivers\etc"
pause

How to remove all folders with a same name within the folder where is located and subfolders using cmd/batch file

I used a tip on how to do what I want, but I have a difficulty, the folders that begin with "!" ex.: c:\!test and in the middle is "." ex.: c:\test.test are not erased. You can help me?
#Echo OFF
echo.
setlocal enabledelayedexpansion
echo Search...
FOR /R %root% %%A IN (.) DO (
if '%%A'=='' goto end
set dir="%%A"
set dir=!dir:.=!
set directory=%%A
set directory=!directory:.=!
set directory=!directory::=!
set directory=!directory:\=;!
for /f "tokens=* delims=;" %%P in ("!directory!") do call :loop %%P
)
:end
echo.
echo Finished.
echo Press any key to exit...
pause >nul
endlocal
exit
:loop
if '%1'=='' goto endloop
if '%1'=='history' (
rd /S /Q !dir!
echo !dir! was deleted.
)
SHIFT
goto :loop
:endloop
I think your code checks every folder and if it finds ones called history then they are all deleted.
If that is the task then this should do the same thing.
#echo off
FOR /D /R %root% %%A IN (*) DO if /i "%%~nxA"=="history" if exist "%%A\" rd /s /q "%%A" & echo "%%A" has been deleted

Resources