Finding Duplicate files in a specific directory and eliminating them - Batch - batch-file

How could we find duplicated files in a certain folder and its sub-folders with also the possibility to eliminate them at the user's will?
Well, this is a way i found that this could be possible. The file and directory are not variable, are fixed and the user would have to edit the code in the program each time it wanted another file and/or another directory to work with.
I recently asked a question about my program and as promissed i would share it when it would be completed.
The program finds the duplicates in a folder and sub-folders of the directory chosen, lists them by order from ancient to the most recent one and it gives the user the choice to eliminate the files, file by file, at the user's will (telling the user which file is up to being deleted/eliminated).
Im very new to this kind of programming so if it is not the prettiest of programs im sorry, but it works and i haven't found something like this anywhere. I hope this helps someone!
#echo off
setlocal EnableDelayedExpansion
set "source_folder=C:\Desktop\Batch testes\Teste 1\Giorgio.docx"
echo Welcome to this Practice/Test Program
echo This program has the obective of finding duplicated files.
pause
echo The user will have the chance to eliminate these files if he wishes
echo There will be the identification of the oldest and the newest file
pause
echo Let us start...
pause
:aPrompt
cls
echo ========================================
echo What do you wish to do?
echo 1.Show only the duplicated files. (Clique '1')
echo 2.Show the duplicated files and eliminate them. (Clique '2')
echo 3.Exit the program (Clique '3')
choice /n /c:123 /M "Escolha uma opcao "%1
goto Alfa-%errorlevel%
:Alfa-1 A1
echo Showing the files being analysed
forfiles /P "C:\Desktop\Batch testes\Teste 1" /M Giorgio.docx /S /C "cmd /c echo #file"
echo Showing the paths of the files being analysed
forfiles /P "C:\Desktop\Batch testes\Teste 1" /M Giorgio.docx /S /C "cmd /c echo #relpath#fname"
pause
echo ===============================================================================
echo.
echo The files are set by order from the oldest (on top) to the most recent (on the bottom)
echo.
(for /f "delims=" %%a in ('dir /a-d /t:w /s /b "C:\Desktop\Batch testes\Teste 1\*Giorgio.docx"') do #echo %%~Ta %%a)
echo.
echo The oldest file is on top of the list. The most recent file is at the bottom of the list
echo.
echo=======================
echo=======================
pause
:bPrompt
echo Here are the duplicated files
echo Do you wish to leave or go back? (Type '1' to end the program, '2' to return to the previous menu)
choice /n /c:12 /M "Pick an option "%1
goto Bravo-%errorlevel%
:Bravo-1 B
echo The program will now end
pause
exit
:Bravo-2 B
echo You chose to go back
pause
goto :aPrompt
:Alfa-2 A2
echo You chose to show and eliminate the duplicated files
pause
echo Showing the files paths
forfiles /P "C:\Desktop\Batch testes\Teste 1" /M Giorgio.docx /S /C "cmd /c echo #relpath#fname"
echo Files identyfied by the the program (it serves the purpose of confirming if they are the right files)
forfiles /P "C:\Desktop\Batch testes\Teste 1" /M Giorgio.docx /S /C "cmd /c echo #file"
echo The files are set by order from the oldest (on top) to the most recent (on the bottom)
echo.
(for /f "delims=" %%a in ('dir /a-d /t:w /s /b "C:\Desktop\Batch testes\Teste 1\*Giorgio.docx"') do #echo %%~Ta %%a)
echo.
echo The oldest file is on top of the list. The most recent file is at the bottom of the list
echo You sure you want to delete the files? (Type '1' to eliminate them, '2' to not eliminate)
:cPrompt
choice /n /c:12 /M "Pick an option "%1
goto Charlie-%errorlevel%
:Charlie-1 C1
echo You chose to delete the files
echo The files will be deleted according to your decision
echo For each file it will be asked if you wish to delete it
pause
del /p /s "C:\Desktop\Batch testes\Teste 1"\*Giorgio.docx
echo The files have been deleted at your choice
pause
:dPrompt
echo Do you wish to exit the program or go back? (Type '1' to end the program, type '2' to go back to the main menu)
choice /n /c:12 /M "Pick an option "%1
goto Delta-%errorlevel%
:Delta-1 D1
echo You chose to leave. The program will shut down
pause
exit
:Delta-2 D2
echo You chose to go back to the main menu
pause
goto :aPrompt
:Charlie-2 C2
:ePrompt
echo You chose not to delete the files.
echo Do you wish to go back to the main menu or to leave? (Type '1' to go back to the main menu, '2' to leave the program)
choice /n /c:12 /M "Pick an option "%1
goto Evo-%errorlevel%
:Evo-1 E1
echo You chose to go back to the main menu
pause
goto :aPrompt
:Evo-2 E2
echo You chose to exit the program. The program will shut down now
pause
exit
:Alfa-3 A3
echo The program will shut down then
pause
exit
If by any case something is failing/giving an error, tell me and i'll fix it because i may have copied something wrong by mistake (like a typo or a missing "(", something).
( I don't know how i could share my program without using the "ask a question" function, im sorry if i broke any rules of this website)
Special thanks to Stephan that helped me previously and without him i couldn't complete the part where i set the oldest and recent file!

Related

Batch For /R Results to be set menu choice

need a bit of help with a project.
Scenario :-
Manually migrating PC's to new Domain breaks a piece of software due to the new profile not having the settings from the old user profile - required to make it run. The old profile is called one thing, the new one - something else e.g.
C:\Users\Sue.Barnes.B3209 (old) C:\Users\Susan.Barnes.NGP (new)
Within the %localappdata% of each (old) profile there "maybe" a config file for this software, if the user has used it previously. E.g.
C:\Users\Sue.Barnes.B3209\AppData\Local\Acme_Limited\Acme.exe_Url_m5l4ujc5t22f3qw0q5uz1dwlfcnrdaoh\1.0.0.15\user.config
Objectives :-
I want to be able to scan through the C:\Users Folder and report back the full path, name & extension of file where it is found, then have the list set in a menu choice where upon input choice will copy the user.config file to the exact same location but in the currently logged on new profile appdata folder.
e.g.
Enumerating List Of User Profiles in the System...
Admin
Public
User
From the Profiles detecting active Configs...
C:\Users\Admin\AppData\Local\Acme_Limited\Acme.exe_Url_m5l4ujc5t22f3qw0q5uz1dwlfcnrdaoh\1.0.0.15\user.config
C:\Users\Public\AppData\Local\Acme_Limited\Acme.exe_Url_m5l4ujc5t22f3qw0q5uz1dwlfcnrdaoh\1.0.0.15\user.config
Press any key to continue . . .
However it is at this point I'm out of my depth. I cant seem to be able to create a choices menu of each instance where the file is found. However many are found, I'd like a number to be printed on the screen so I can choose the correct config to copy to the newly set up profile. Simply,
Xcopy /f C:\Users\Sue.Barnes.B3209\AppData\Local\Acme_Limited\Acme.exe_Url_m5l4ujc5t22f3qw0q5uz1dwlfcnrdaoh\1.0.0.15\user.config
%localappdata%\Acme_Limited\Acme.exe_Url_m5l4ujc5t22f3qw0q5uz1dwlfcnrdaoh\1.0.0.15\
Current code base :-
echo.
echo Enumerating List Of User Profiles in the System...
echo.
TIMEOUT /T 3 >NUL
dir /b C:\Users
echo.
echo From the Profiles detecting active Configs...
echo.
TIMEOUT /T 3 >NUL
for /R "C:\Users" %%a in (1.0.0.15\user.config*) do (
echo %%~dpnxa
)
)
echo.
pause
Any help be greatly appreciated, thanks
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
set "dontshow=u:\dontshow.txt"
set "configs=u:\configs.txt"
set "profiles=u:\profiles.txt"
:again
echo :>>"%dontshow%"
del "%configs%" >nul 2>nul
del "%profiles%" >nul 2>nul
:: Find all of the "user.config" files having ..\appdata\local\Acme_limited\...1.0.0.15
FOR /f "tokens=1-9delims=\" %%a IN (
'dir /s /b /a-d "%sourcedir%\user.config" '
) DO if /i "%%d"=="appdata" if /i "%%e"=="local" if /i "%%f"=="Acme_Limited" if /i "%%h"=="1.0.0.15" (
rem these are the users' config files that may be copied.
echo %%c|findstr /x /g:"%dontshow%" /i /L >nul
if errorlevel 1 >>"%configs%" echo %%c
)
:: Find all of the user profiles that are not in "dontshow" and do NOT have "user.config" - These are the profiles that may need to be processed
FOR /f "delims=" %%a IN (
'dir /b /ad "%sourcedir%" '
) DO (
echo %%a|findstr /x /g:"%dontshow%" /i /L >nul
if errorlevel 1 echo %%a|findstr /x /g:"%configs%" /i /L >nul
if errorlevel 1 >>"%profiles%" echo %%a
)
:: Now we have a list of profiles with "user.config" missing in %profiles%
:: And possible source-profiles in %configs%
:: Show the list of "config missing" profiles
cls
findstr /n /v /L /c:":" "%profiles%"
:reselectd
set "selectiond="
set /p "selectiond=Choose destination profile "
if not defined selectiond goto :eof
for /f "tokens=1*delims=:" %%a in ('findstr /n /v /L /c:":" "%profiles%"') do if "%%a"=="%selectiond%" set "selectiond=%%b"&goto selects
echo Invalid selection
goto reselectd
:selects
for /L %%a in (1,1,4) do echo.
findstr /n /v /L /c:":" "%configs%"
:reselects
set "selections="
set /p "selections=Choose source profile "
if not defined selections goto :eof
for /f "tokens=1*delims=:" %%a in ('findstr /n /v /L /c:":" "%configs%"') do if "%%a"=="%selections%" set "selections=%%b"&goto process
echo Invalid selection
goto reselects
:process
echo Copy from profile "%selections%" to "%selectiond%" ?
choice
if errorlevel 2 goto again
:: Do the copy... just echoed, remove `echo` keyword to activate
ECHO md "%sourcedir%\%selectiond%\appdata\localAcme_Limited\whatever\1.0.0.15"
ECHO copy "%sourcedir%\%selections%\appdata\localAcme_Limited\whatever\1.0.0.15\user.config" "%sourcedir%\%selectiond%\appdata\localAcme_Limited\whatever\1.0.0.15"
choice /M "Add '%selections%' to processed file ? "
if errorlevel 2 goto processedd
>>"%dontshow%" echo %selections%
:processedd
choice /M "Add '%selectiond%' to processed file ? "
if errorlevel 2 goto again
>>"%dontshow%" echo %selectiond%
goto again
Interesting exercise. Lack of information about what Acme.exe_Url_m5l4ujc5t22f3qw0q5uz1dwlfcnrdaoh is about (constant string, change-per-user? What?), though - left as an exercise for OP to resolve.
You would need to change the setting of sourcedir to suit your circumstances. The listing uses a setting that suits my system.
I decided that the key part is the third directory level - the user-id. This approach uses files of user-id, two are temporary and one is permanent - "dontshow.txt" which contains a list of user-ids NOT to show. This can be manually maintained using an editor if required.
So - to start, add a line containing a single colon to the "dontshow" file. This is a dummy which can never match a real user-id and is required because findstr doesn't like an empty dictionary file.
The first step is to find all of the user.config files, and use for /f to process the filenames found, selecting the significant directory-levels. Having excluded any path that does not fit the criteria, the third level contents is matched against the exclusions in "dontshow.txt". If the name found is new, add it to the configs file.
Second verse - same as the first, but this time only looking at the directory names. Note that the entry is made to profiles if the name found is NOT on the dontshow list AND is also NOT on the config list.
Now select a destination profile by listing profiles and appending a prefix linenumber: using findstr. Enter a number (manual entry, unchecked) and then match the line number by using for/f.
Rinse and repeat for the configs file for the source profile.
Display the proposed command, accept a Y/N response then ask whether each name should be added to the dontshow list.
And straight on 'til morning.
Note that responding with Return to any of the set /p commands will exit the batch.

Keep 2 specific folders using RMDIR

As part of my job I need to remove files from computers that are being shipped over seas, this task is done several times a week and can be scripted, however I am terrible with script, I am in no means a coder of any sort.
My issue is that I need to clear out the C:\Users folder whilst keeping the Public and Default folders. I know how to remove a directory and all subfolders however I don't know how to keep just those two folders.
The code I have so far is:
#Echo off
color F
:Choice
Echo.
Echo.
set choice=
set /p choice="Type Y to proceed or N to close the tool and then press ENTER:----"
IF '%Choice%' =='Y' GOTO DELETE
IF '%Choice%' =='y' GOTO DELETE
IF '%Choice%' =='N' GOTO END
IF '%Choice%' =='n' GOTO END
:DELETE
rmdir /S /Q C:\***PATH***\***FOLDERNAME***
rmdir /S /Q C:\***PATH***\***FOLDERNAME***
rmdir /S /Q C:\***PATH***\***FOLDERNAME***
rmdir /S /Q C:\***PATH***\***FOLDERNAME***
Echo.
Echo.
#Echo All Files Removed
GOTO END
:END
echo.
echo.
Echo *****...Closing programme... Please wait...*****
Timeout /t 3
exit
Do you know if this is possible?
The following method, ran As Administrator, may work for you:
#Echo Off
Color 0F
Echo=&Echo=
Choice /N /M "Type Y to proceed or N to close the tool"
If ErrorLevel 2 Exit /B
For /F Tokens^=2^Delims^=^" %%A In ('WMIC Path Win32_UserProfile Where^
"Special!='True'" Assoc /AssocClass:Win32_UserAccount 2^>Nul'
) Do WMIC UserAccount Where "SID='%%A' And LocalAccount='TRUE'" Delete
Echo=&Echo=&Echo All Files Removed&Echo=&Echo=
Echo *****...Closing programme... Please wait...*****
Timeout 3 /NoBreak>Nul
Exit /B
Special!='True' will ignore special accounts, which include Administrator, Public and Default.

Batch Coding - Choose command not returning the correct answer

I am trying to create a batch file which has two options:
Create a series of folders with custom names (defined by variables inputted by the user)
OR
Create the same as before except also, once completed, automatically
copying all appropriate files to the appropriate folders in the
structure.
The idea is that with this batch file I could keep my film projects (As I am a freelance filmmaker working with my brother) in exactly the same folder structures across all 3 of our computers. AKA a uniform Project folder structure can be implemented with a simple double click and a few variables to fill in, while in the case of option 2 any files found on a specified SD Card are also moved to the appropriate folders within the structure.
The actual xcopy commands and mkdir commands etc. work exactly how they are supposed to.
Since the different computers will be allocating different drive letters depending on what is already attached to the computer before entering the SD Card into the card reader, I will never know what the drive letter of the SD Card will be (from which the footage and images will be loaded onto the computers).
For example:
One computer could have an external hard drive in (of which we have a few) at the time of the SD Card being plugged in, while another may have only the SD Card as an external device.
The code below is the complete .bat file including past code which I had tried but didn't work or needed to be excluded for some reason. I have some lines of code in comments so I know what I had tried in the past, these are obviously not meant to be used anymore.
:Menu
ECHO OFF
CLS
ECHO OFF
TITLE Saborknight Productions - Project Creator
ECHO.
ECHO ...............................................
ECHO PRESS the appropriate number to select your task, or 3 to EXIT.
ECHO ...............................................
ECHO.
ECHO 1 - Create Saborknight Default folder Hierarchy within a project folder
::(Disabled)ECHO 2 - Create Saborknight Default folder Hierarchy AND copy ALL files from SD Card to the appropriate folder
ECHO 3 - EXIT
ECHO.
ECHO WARNING - Option 2 will delete the files from the Recording Device automatically. Secure the device before proceeding!
ECHO.
ECHO.
CHOICE /c 123 /n
IF ERRORLEVEL 3 EXIT
IF ERRORLEVEL 2 GOTO :CREATE
IF ERRORLEVEL 1 GOTO :CREATE
::End of Menu
---------------------------------------------------------------------------------------------
:CREATE
::Creates DIR Folder Structure as per Saborknight Productions Standard
ECHO OFF
CLS
::Variables Descriptor
SET /P project_name=Enter the Project Name: || SET project_name=NothingChosen
If "%project_name%"=="NothingChosen" (
GOTO ERROR_PROJECT
) ELSE (
GOTO CREATOR
)
:ERROR_PROJECT
::If no Project Name is entered
ECHO Please enter the Project Name
GOTO CREATE
:CREATOR
::DIR Creator + Confirmation
::Videos DIR
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Footage
::Cut from above MKDIR -> \"Day 1"\%device_name%
::Images DIR
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Images\%device_name%
::Audio DIR -> Soundtracks
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Audio\Soundtracks
::Audio DIR -> Recordings
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Audio\Recordings
::Audio DIR -> Sound FX
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Audio\"Sound FX"
::Premier Project DIR
ECHO OFF
MKDIR D:\Dropbox\"Project Files"\"%project_name%"
ECHO The Folder Structure has been created
ECHO.
ECHO.
ECHO What would you like to do next?
Echo.
ECHO 1 - View Created Folder Structure
ECHO 2 - Go to Menu
ECHO 3 - EXIT
::Choice is invisible
CHOICE /c 123 /n
IF ERRORLEVEL 3 EXIT
IF ERRORLEVEL 2 GOTO MENU
IF ERRORLEVEL 1 GOTO VIEW
::End of CREATE
---------------------------------------------------------------------------------------------
:COPY
::Creates DIR Folder Structure as per Saborknight Productions Standard + Copying/Moving Files from a selected SD Card connected to the computer
ECHO OFF
CLS
:COPY_PROJECT
::Project Variable Descriptor
SET /P project_name=Enter the Project Name: || SET project_name=NothingChosen
If "%project_name%"=="NothingChosen" (
GOTO ERROR_COPY_PROJECT
) ELSE (
GOTO COPY_DEVICE_NAME
)
::If True, Process continues
:COPY_DEVICE_NAME
::Device Name Variable Descriptor
ECHO.
SET /P device_name=Enter the Name of the Recording Device: || SET device_name=NothingChosen
If "%device_name%"=="NothingChosen" (GOTO DAMN_DEVICE) ELSE (GOTO DEVICE_DIR)
:DEVICE_DIR
::Device DIR Variable Descriptor
ECHO.
::Selecting the location of the SD Card of the Recording Device + Confirmation
ECHO Copy files from drive: E, F, G, H or I?
SET _drive=G
::SETLOCAL EnableDelayedExpansion
::CHOICE /c fgehi
::IF ERRORLEVEL 5 SET _drive=I
::IF ERRORLEVEL 4 SET _drive=H
::IF ERRORLEVEL 3 SET _drive=G
::IF ERRORLEVEL 2 SET _drive=F
::IF ERRORLEVEL 1 SET _drive=E
ECHO.
ECHO You have selected drive %_drive%:
ECHO.
::DIR Creator + Confirmation -> Only if Device Drive is successfully selected
::Videos DIR
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Footage\"Day 1"\"%device_name%"
::Images DIR
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Images\"%device_name%"
::Audio DIR -> Soundtracks
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Audio\Soundtracks
::Audio DIR -> Recordings
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Audio\Recordings
::Audio DIR -> Sound FX
ECHO OFF
MKDIR D:\"Movie Projects"\"%project_name%"\Audio\"Sound FX"
::Premier Project DIR
::ECHO OFF
::(Disabled for Testing)MKDIR D:\Dropbox\"Project Files"\"%project_name%"
ECHO.
CHOICE /c YN /m "Would you like files to be deleted automatically from the device? Press Y=Yes or N=No"
IF ERRORLEVEL 2 GOTO NO_DELETE
IF ERRORLEVEL 1 GOTO DELETE
:NO_DELETE
::No Deletion once Copied from Device
::For Copying Videos
ECHO.
ECHO Copying Videos
XCOPY %_drive%:\DCIM\ "D:\Movie Projects\"%project_name%"\Footage\"Day 1"\"%device_name%"\" *.MOV *.mp4 /V /-Y
::COPY %_drive%:\DCIM\ "D:\Movie Projects\"%project_name%"\Footage\"Day 1"\"%device_name%"\" *.MOV *.mp4
::ROBOCOPY %_drive%:\DCIM "D:\"Movie Projects"\"%project_name%"\Footage\"Day 1"\"%device_name%"\*" *.mov *.mp4 /mir /copy:DATO /np /eta /log+:"Log - Footage CopyOnly.txt" /nosd /nodd
PAUSE
::For Copying Images
ECHO.
ECHO Copying Images
XCOPY %_drive%:\DCIM\ "D:\Movie Projects\"%project_name%"\Images\"%device_name%"\" *.MOV *.mp4 /V /-Y
::COPY %_drive%:\DCIM\*.jpg;*.png;*.cr2 "D:\Movie Projects\"%project_name%"\Images\"%device_name%"\" /V /-Y
::ROBOCOPY %_drive%:\DCIM "D:\"Movie Projects"\"%project_name%"\Footage\"Day 1"\"%device_name%"" *.jpg *.png *.cr2 /copy:DATO /mir /np /eta /log+:"Log - Images Copy Only.txt" /nosd /nodd
PAUSE
GOTO SUCCESS_MSG
:DELETE
::Copying with Automatic Deletion once Copied
::For Copying and Deleting Videos
ECHO Copying and Deleting Videos
MOVE %_drive%:\DCIM\*.mov;*.mp4 D:\"Movie Projects"\"%project_name%"\Footage\"Day 1"\"%device_name%"\ /-Y
::ROBOCOPY %_drive%:\DCIM D:\"Movie Projects"\"%project_name%"\Footage\"Day 1"\"%device_name%" *.mov *.mp4 /mov /copy:DATO /np /eta /log+:"Log - Footage Copy Delete.txt" /nosd /nodd
PAUSE
::For Copying and Deleting Images
ECHO Copying and Deleting Images
MOVE %_drive%:\DCIM\*.jpg;*.png;*.cr2 D:\"Movie Projects"\"%project_name%"\Images\"%device_name%"\ /-Y
::ROBOCOPY %_drive%:\DCIM D:\"Movie Projects"\"%project_name%"\Images\"%device_name%" *.jpg *.png *.cr2 /mov /copy:DATO /np /eta /log+:"Log - Images Copy Delete.txt" /nosd /nodd
PAUSE
GOTO SUCCESS_MSG
:SUCCESS_MSG
::Only if all Copying/Moving and DIR Creation Processes are Completed Successfully
ECHO.
ECHO The Folder Structure has been created and files copied/moved
ECHO.
ECHO.
ECHO What would you like to do next?
Echo.
ECHO 1 - View Created Folder Structure
ECHO 2 - Go to Menu
ECHO 3 - EXIT
::Choice is invisible
CHOICE /c 123 /n
IF ERRORLEVEL 3 EXIT
IF ERRORLEVEL 2 GOTO MENU
IF ERRORLEVEL 1 GOTO :VIEW
:DAMN_DEVICE
ECHO.
ECHO Please enter the Device Name, Re-entering the Project Name
ECHO.
GOTO COPY
:ERROR_COPY_PROJECT
::If no Project Name is entered
ECHO.
ECHO Please enter the Project Name
ECHO.
GOTO COPY_PROJECT
ENDLOCAL
::End Of COPY
---------------------------------------------------------------------------------------------
:VIEW
ECHO OFF
CLS
TREE D:\"Movie Projects"\"%project_name%"
ECHo.
ECHO Press any key to return to Menu
ECHO.
PAUSE
GOTO MENU
::End of VIEW
The Problem
In this part of the code, the CHOOSE command wont choose the correct choice:
#ECHO OFF
CHOICE /c fgehi
IF ERRORLEVEL 5 SET _drive=I
IF ERRORLEVEL 4 SET _drive=H
IF ERRORLEVEL 3 SET _drive=E
IF ERRORLEVEL 2 SET _drive=G
IF ERRORLEVEL 1 SET _drive=F
Pause
ECHO.
ECHO You have selected drive %_drive%:
ECHO.
Pause
The Evidence of the Problem being a problem
I tested the Batch file on two separate machines (One by remote access so that the two screens lay side by side) and can be viewed here: Image of the Problem being a problem...
Apologies for the dirtiest code in history with a complete overuse of comments. This was supposed to be a one night project which has turned into a month long project and I still haven't solved it!
Even a programming friend of mine cannot explain why it wont work.
All help much appreciated in advance!!!
Also any alternative suggestions to complete the described tasks above are definitely welcome, I love learning new code!
Saborknight
Your program fail because IF ERRORLEVEL n ... "execute the command if the errorlevel is GREATER OR EQUAL than the number given", that is, you placed the IF commands in the opposite order. This works correctly:
#ECHO OFF
CHOICE /c fgehi
IF ERRORLEVEL 1 SET _drive=F
IF ERRORLEVEL 2 SET _drive=G
IF ERRORLEVEL 3 SET _drive=E
IF ERRORLEVEL 4 SET _drive=H
IF ERRORLEVEL 5 SET _drive=I
Pause
ECHO.
ECHO You have selected drive %_drive%:
ECHO.
Pause
May I suggest you a different, simpler method?
#ECHO OFF
SET option=0FGEHI
CHOICE /c fgehi
CALL SET _drive=%%option:~%ERRORLEVEL%,1%%
ECHO.
ECHO You have selected drive %_drive%:
ECHO.
Pause
As documented here: http://www.robvanderwoude.com/choice.php
By the way, in Windows NT 4 this won't work, since the SET command itself will set an errorlevel (usually 0)!
However, Windows NT makes it easy by storing the latest errorlevel in the environment variable ERRORLEVEL
This works for me:
#ECHO OFF
CHOICE /c fgehi
IF %ERRORLEVEL% EQU 5 SET _drive=I
IF %ERRORLEVEL% EQU 4 SET _drive=H
IF %ERRORLEVEL% EQU 3 SET _drive=E
IF %ERRORLEVEL% EQU 2 SET _drive=G
IF %ERRORLEVEL% EQU 1 SET _drive=F
Pause
ECHO.
ECHO You have selected drive %_drive%:
ECHO.
Pause
Unless you know the proper ritual to ask the Microsoft gods for forgiveness, I would recommend you stay away from batch, it is a lot of trouble.
Even PowerShell is much less of a hassle.

Two For Loops Using %1 - Delayed Expansion?

My working batch file scans a long list of remote servers, copies anything there to a local server, checks the log file for a keyword, and if the keyword is found sends an email. I noticed it is always sending emails, even with a blank log file.
I discovered both FOR loops are using the %1 variable for their output - as seen in ECHO %1 and each line of the called :servermove. For lack of a better explanation it is not resetting %1 to null between loops.
I reviewed almost a dozen SO posts and am somewhat confident using SETLOCAL ENABLEDELAYEDEXPANSION would resolve this. That is where my understanding ends and I am unsuccessful thus far.
Here is the relevant code:
SET DATE=%date:~4,2%-%date:~7,2%-%date:~10,4%
SET HH=%time:~0,2%
SET MN=%time:~3,2%
SET TSTAMP=Time Run is %HH%%MN%
SET DATETIME=%DATE% at %HH%%MN%
SET LOGFILE="\\nt980a3\CreditFileImagesTransmission\LogFiles\%DATETIME%-File Move Log.txt"
SET MailDst=
SET MailSrc=
SET MailSrcName=Center to LDSD File Mover
SET OKMailSub=A Branch Has Sent You Some Files
ECHO %DATETIME% > %LOGFILE%
ECHO. >> %LOGFILE%
FOR /F "tokens=1" %%A IN (%~dp0SourceServers.txt) DO CALL :ServerMove %%A
:cleanuplogs
PUSHD "\\nt980a3\CreditFileImagesTransmission\LogFiles" &&(
FORFILES /S /M *.txt /D -45 /C "CMD /C DEL /Q #path"
) & POPD
:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"
:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit
:successmail
IF EXIST %temp%\to.txt DEL %temp%\to.txt
FOR %%a IN (%MailDst%) DO ECHO %%a>>%temp%\to.txt
"%~dp0sendmail.exe" /TO=%temp%\to.txt /FROM=%MailSrcName% ^<%MailSrc%^> /REF=%OKMailSub% /MESSAGE=%LOGFILE% /HOST=
:exit
EXIT
:ServerMove
DIR /S /B \\%1\CreditFileImagesTransmission\*.* >> %LOGFILE%
XCOPY /E /C /I /Y "\\%1\CreditFileImagesTransmission\*.*" "\\nt980a3\CreditFileImagesTransmission\%DATE%\%HH%%MN%\"
FOR /D %%P IN ("\\%1\CreditFileImagesTransmission\*.*") DO RMDIR "%%P" /Q /S
DEL /Q /S "\\%1\CreditFileImagesTransmission\*.*"
I tried changing :mailtest to use %%B in both instances but that also fails. Placing SETLOCAL ENABLEDELAYEDEXPANSION and its counterpart ENDLOCAL before one or the other loop and changing the %%A to !A! does not work either.
Would someone kindly point out the error in my ways and offer suggestions or resources that will help me resolve this?
%1 is the first parameter provided to the procedure - either from the command-line (in the main procedure) or the parameter following the procedure name in call :procedurename parameter1.
In your case, %1 to :servermove is an entry from SourceServers.txt and %1 to :searchlog is each line from %LOGFILE%.
Since you've censored your batch, what you've posted makes little sense. For instance, the :searchlogs routine will take the first line from %LOGFILE% and go to successmail or cleanlogs depending on whether that first line contains the target string \\nt. What it does from there, we can't tell.
We're faced with an XY problem - trying to fix a solution, not a problem.
First problem: Don't use date as a user-variable. It's a "magic variable" which contains the date but it's overridden by a specific set statement.
Having run :servermove for each entry in SourceServers.txt, you are
- accumulating a directory list from \CreditFileImagesTransmission\*.* on that server.
- copying those files to server nt980a3 with a date/timestamp but not including the source-servername so any duplicate name anywhere will overwrite an earlier version. I suggest you include %1 into your destination-name.
- deleting subdirectories
- deleting files.
I'd suggest you simply remove the directory \\%1\CreditFileImagesTransmission\, then re-create it.
I'd also suggest that you add an extra line
goto :eof
after the del /q /s... line. This will cause execution to be transferred to the end-of-file (the colon in :eof is required) and may seem superfluous, but it ensures that the routine has a defined endpoint - if you add a further routine, there is no way the :servermove routine will continue into your new code.
After each server has been processed, you proceed to the :cleanuplogs routine, which I presume deletes logs older than 45 days.
Your next statement is a real problem. What it will do is grab the very first line of the logfile (which contains "%DATE% at %HH%%MN%" with the date resolved as you've set at the start and it then processes this line in :searchlog; there is no \\nt in this line, so errorlevel is set to 1, and the batch proceeds to :EXIT (not a good label in my view, since it's a keyword); executes an exitand should terminate the batch.
This appears not to be what it is actually doing, and I'm at a loss to explain why.
I'd suggest changing
:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"
:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit
to
:mailtest
find "\\nt" %LOGFILE%>NUL
IF NOT ERRORLEVEL 1 GOTO successmail
:failmail
echo "\\nt" was found in the log
pause
GOTO exit
but I can't test that...
:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"
You are missing a GOTO :EOF or similar goto here because it will drop through to the routine below once the above is finished.
:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit
I feel you can not carry the %1 of first for loop to others. Try to transfer that to another variable like below.
:ServerMove
set servername=%1
DIR /S /B \\%servername%\CreditFileImagesTransmission\*.* >> %LOGFILE%
XCOPY /E /C /I /Y "\\%servername%\CreditFileImagesTransmission\*.*" "\\nt980a3\CreditFileImagesTransmission\%DATE%\%HH%%MN%\"
FOR /D %%P IN ("\\%servername%\CreditFileImagesTransmission\*.*") DO RMDIR "%%P" /Q /S
DEL /Q /S "\\%servername%\CreditFileImagesTransmission\*.*"
Cheers, G

DIR /p pausing not working...?

I am having a problem. I need my code to list all the text files in a big directory and pause at each full screen. I set it up so that users will be able to input the number that is listed beside every txt file in the list but the /p parameter refuses to pause the list...
DIR SAVES\*.txt /B /P |FIND /V /N "//"
ECHO.
ECHO (Press "Q" to EXIT to the main menu)
ECHO.
CHOICE /C DLVQ /N /M "Would you like to DELETE, LOAD, or VIEW a file [D/L/V]?"
IF ERRORLEVEL 4 GOTO MENU
IF ERRORLEVEL 3 GOTO VIEW
IF ERRORLEVEL 2 GOTO LOAD1
IF ERRORLEVEL 1 GOTO DELETE
:DELETE
ECHO.
SET /P C=Choose the file number [#] to DELETE (and press ENTER):
FOR /F "usebackq tokens=1,2* delims=[]" %%d IN (`DIR SAVES\*.txt /B ^|FIND /V /N "//"`) DO (
IF /I !C! EQU q (GOTO MENU)
IF !C! EQU %%d (
ECHO.
CHOICE /N /M "Are you sure you want to DELETE %%e [Y/N]?"
IF ERRORLEVEL 2 GOTO LOAD
DEL /Q "SAVES\%%e"
DEL /Q "SAVES\"%%~ne"_stats"
IF EXIST "SAVES\%%e" (
IF EXIST "SAVES\"%%~ne"_stats" (
GOTO DELETE1
The folder could potentially have hundreds of txt save files and i need the ability to run this script in its own cmd window and pause as the screen fills up with info. Running my whole utility as a .bat means there is NO scrollbar available for users to view all the files. How can I make the /P pause parameter work?
You're piping the output of dir to find. find itself doesn't do pagination and simply outputs anything it matches in the input. dir itself can't do the pagination in this case, because find would be unable to do the input to advance to the next page, so you've effectively disabled pagination.
Try
dir | find | more

Resources