Ignore one folder and its contents in batch operation - batch-file

I've tried to create a batch file that will remove all files and sub-directories from a folder. The command I found that worked is this
FORFILES /p “X:\DAILY\1 MONDAY” /m *.* /c “cmd /c Del /F /Q #path” /d -7 /s & FORFILES /p “X:\DAILY\1 MONDAY” /S /D -7 /C “cmd /c IF #isdir == TRUE rd /S /Q #path”
Now my users tell me there is a Reference folder under 1 MONDAY that they don't want purged (but all other subdirectories should be emptied and deleted.) Can anyone advise how I might accomplish that?
Thank you!

for /f %%a in ("X:\Daily\1 MONDAY\*") do (if %%a neq "<filename you want to save>" (del %%a))
NOT YET TESTED
This should work though. Put the files you want to save in <filename you want to save>

It is extremely inefficient to use FORFILES for such a task because FORFILES has to start cmd.exe for each file found to delete the file older than seven days and for each folder to remove.
A much better solution would be:
#echo off
%SystemRoot%\System32\robocopy.exe "X:\DAILY\1 MONDAY" "X:\DAILY\1 MONDAY\WeeklyDelete" /E /XD "X:\DAILY\1 MONDAY\WeeklyDelete" "X:\DAILY\1 MONDAY\Reference" /MINAGE:7 /MOVE /NDL /NFL /NJH /NJS
if exist "X:\DAILY\1 MONDAY\WeeklyDelete\" rd /Q /S "X:\DAILY\1 MONDAY\WeeklyDelete"
ROBOCOPY searches
for all files in the directory X:\DAILY\1 MONDAY
and its subdirectories including empty directories because of option /E with
excluding the files in the two directories X:\DAILY\1 MONDAY\WeeklyDelete and X:\DAILY\1 MONDAY\Reference and all their subdirectories because of option /XD "X:\DAILY\1 MONDAY\WeeklyDelete" "X:\DAILY\1 MONDAY\Reference" with
excluding all files last modified in last seven days because of option /MINAGE:7.
The found files and folders matching theses criteria are moved to X:\DAILY\1 MONDAY\WeeklyDelete whereby the destination folder is automatically created on not already existing.
The options /NDL /NFL /NJH /NJS are for not printing the list of moved directories, list of moved files, the header and the summary.
A folder is moved only if being empty after moving all files matched by these criteria. So a folder is not moved on containing a file or subfolder.
The option /S instead of /E and the option /MOV instead of /MOVE can be used to move only files and do not move also folders being empty before or after moving the files.
The file and folder movements are done very fast by ROBOCOPY because of destination folder is on same drive as source folder which means just the file system of this drive must be updated and no file data must be moved at all.
An IF condition is used after ROBOCOPY finished with updating the file system to move the files and folders to verify if the destination folder X:\DAILY\1 MONDAY\WeeklyDelete exists. In this case command RD is used to delete this folder quietly because of option /Q and with all files and subdirectories because of option /S. This action is again just a file system update not really deleting file data stored on storage media and so is processed very fast.
Open a command prompt window and execute there the following commands to read more about the used commands in the three lines above.
echo /?
if /?
rd /?
robocopy /?
The commands are described also
by Microsoft with the documentations for the Windows Commands and
by SS64.com with A-Z index of Windows CMD commands and on many other websites.

Based upon your provided information, I would suggest this as your updated batch file:
#%__AppDir__%forfiles.exe /P "X:\DAILY\1 MONDAY" /C "cmd /C If #IsDir == FALSE 0x28Del /A /F #Path0x29 Else If /I Not #File == 0x22Reference0x22 RD /S /Q #Path" /D -7
That's it, nothing else to be added or modified.

Related

Batch script - dir /b is including directory names and empty lines in output file

I run this script to list backup files older than 8 days and delete them in a server, and it behaving weird recently. Please see below
::Find backup files older than 8 days
::/p Specifies the path from which to start the search.
::/s Instructs the forfiles command to search into subdirectories recursively.
::/d Selects files with a last modified date within the specified time frame.
::/c Carries out the command specified by String and then stops.
::/b Displays a bare list of directories and files, with no additional information.
PUSHD \\SERVER_NAME\M$\MSSQL
FORFILES /P Backup /s /d -8 /C "cmd /c dir /B #file">K:\ScriptLogs\OutPut
POPD
This was working fine recently until I created more folders inside \SERVER_NAME\M$\MSSQL\Backup like FULL, DIFF, LOG as
\\SERVER_NAME\M$\MSSQL\Backup\FULL
\\SERVER_NAME\M$\MSSQL\Backup\DIFF
\\SERVER_NAME\M$\MSSQL\Backup\LOG
And the K:\ScriptLogs\OutPut file is now including the folder name FULL as below
FULL
SERVER_NAME_DB_DIFF_2021_06_10_040135.diff
SERVER_NAME_DB_DIFF_2021_06_11_040124.diff
SERVER_NAME_DB_DIFF_2021_06_12_040213_1.diff
I'm not able to understand why it is including FULL in the output list (if my cmd is wrong it should include DIFF and LOG too).
And when i modified the code as below
PUSHD \\SERVER_NAME\M$\MSSQL
FORFILES /P Backup /s /d -8 /C "cmd /c dir /A-D /B #file">K:\ScriptLogs\OutPut
POPD
It gives error as below, and output file is not including FULL now (as /A-D excluded Dir's)
K:\DBScripts>PUSHD \\SERVER_NAME\M$\MSSQL
W:\MSSQL>FORFILES /P Backup /s /d -8 /C "cmd /c dir /A-D /B #file" 1>K:\ScriptLogs\OutPut
File Not Found
File Not Found
W:\MSSQL>POPD
My concern here is why it is including FULL directory name in the older code version and the code run gives error with new version. Thanks for your help.
Thanks #compo ....
PUSHD \\SERVER_NAME\M$\MSSQL
FORFILES /P Backup /S /D -%NUMBER_OF_DAYS% /C "cmd /Q /D /C \"If #IsDir==FALSE For %%G In (#File) Do Echo %%~G\"" 1>K:\ScriptLogs\OutPut-%dtStamp%
POPD
This fixed the issue.

How to copy specific subfolders if existing to new folders in a backup folder using a batch file?

I am a total beginner and I need some help to backup some folders with files from a server.
I need to copy some folders to my local computer.
Folders to copy are like this
\\DistantServer\path\RandomFolder\Config\old
\\DistantServer\path\Another Random Folder\Config\old
...
Those old folders should be copied to:
D:\Backup\RandomFolder\old
D:\Backup\Another Random Folder\old
I tried some codes, but I'm only having errors.
Could anyone help me?
This batch file should work for the task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=\\DistantServer\path"
set "TargetFolder=D:\Backup"
for /D %%I in ("%SourceFolder%\*") do (
if exist "%%I\Config\Old\" (
rd /Q /S "%TargetFolder%\%%~nxI\old" 2>nul
%SystemRoot%\System32\xcopy.exe "%%I\Config\Old" "%TargetFolder%\%%~nxI\old\" /C /E /H /I /K /Q /R /Y >nul
)
)
endlocal
The command FOR searches in source folder as defined with environment variable SourceFolder for non hidden subfolders. Each subfolder found is assigned with full path not ending with a backslash and never enclosed in double quotes to loop variable I referenced with %%I.
The command IF checks for existence of the subfolder Config\old in current subfolder of source folder. The found subfolder is ignored if not containing the subfolder Config\old.
On existence of Config\old in current subfolder of source folder the command RD first removes quietly with all subfolders the appropriate target folder independent on its existence to make sure that the copy done next results in 1:1 folder copy. The RD command can be removed in case of target folder most likely never exists before the copying is done or if it is wanted that existing contents of target folder is merged with current contents of source folder.
%%~nxI references the current subfolder in source folder without path, i.e. without folder path as defined with environment variable SourceFolder.
The command XCOPY copies the entire folder Config\old in current subfolder of source folder to a subfolder old in target folder as defined by environment variable TargetFolder. The entire directory structure to appropriate target folder is automatically created by XCOPY if not already existing because of target specification ends with a backslash being a clear indication for XCOPY that the target string specifies a directory.
Note: The entire code above without command RD could be optimized also to a single command line.
#for /D %%I in ("\\DistantServer\path\*") do #if exist "%%I\Config\Old\" %SystemRoot%\System32\xcopy.exe "%%I\Config\Old" "D:\Backup\%%~nxI\old\" /C /E /H /I /K /Q /R /Y >nul
Single command line with command RD:
#for /D %%I in ("\\DistantServer\path\*") do #if exist "%%I\Config\Old\" rd /Q /S "D:\Backup\%%~nxI\old" 2>nul & %SystemRoot%\System32\xcopy.exe "%%I\Config\Old" "D:\Backup\%%~nxI\old\" /C /E /H /I /K /Q /R /Y >nul
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 /?
endlocal /?
for /?
if /?
rd /?
set /?
setlocal /?
xcopy /?
Read also the Microsoft article about Using Command Redirection Operators for an explanation of >nul and 2>nul. And read answer on Single line with multiple commands using Windows batch file for an explanation of operator & as used in the last batch code (single command line with RD).

Scheduled Folder Cleanup - Batch File

I am currently working at my first Junior IT position, and I am having trouble with a simple batch file.
Essentially the file is ran weekly through the task scheduler. It removes files and folders from a server directory that are older than 8 days. It is also supposed to remove empty folders.
forfiles /p "P:\blahblah" /s /m * /d -8 /c "cmd /c del /Q /S /F /A #path"
cd /d P:\blahblah
for /f "usebackq" %%d in (`"dir /ad/b/s | sort /R"`) do rd "%%d"
REM robocopy "P:\blahblah" "P:\blahblah" /s /move"
There are two problems here;
It will occasionally delete files only a few days old.
It will not remove empty folders.
The file was written by an old junior IT employee and there is no documentation. My guess is multiple methods were used in order to ensure the cleanup (ironically). I have searched google and here are my current thoughts on each command..
1) forfiles - the forfiles command seems to be written correctly and I do not see any issues with it.
2) cd - simple enough
3) for - not entirely sure. The batch variables are new to me and I am not sure if it is working correctly.
4) robocopy - I have not been able to find an instance online where someone copies a directory to itself for cleanup. I also notice the extra quotation in there, but i am not certain of its incorrectness. This line especially seems odd to me.
Normally I would try and test my through something like this, but It is a bit harder to test quickly given I need to see if it is removing things based on calendar date. That's why I am here!
I promise I would not have asked if I had not already scoured the internet for an idea. Any help would be greatly appreciated, and I would love to learn a little more about the above commands!
Thanks for your help!
forfiles
Being syntactically correct doesn't mean it does what you want, it does what you ask. Here the problem is the del command. It will delete what the forfiles has selected, but you should test the selected element is not a folder. If you call del /q /s /f /a with a folder reference, you delete the folder contents.
cd
Simple enough, but as you don't check the operation was sucessful (maybe P: is not available) maybe the following for command removes information where it should not.
for
As Squashman comments, if you change the back quotes into single quotes you will not need the usebackq.
But you need the delims clause to avoid problems with paths containing spaces. for /f does not iterate over file references, but over lines of text (in this case generated by a dir command). By default tabs and spaces are delimiters that split the lines being processed and, also by default, only the first token is retrieved. Setting the delims clause to an empty list of characters will disable this behaviour.
You can try with something like
#echo off
setlocal enableextensions disabledelayedexpansion
pushd "p:\blahblah" && (
forfiles /s /m * /d -8 /c "cmd /c if #isdir==FALSE del /q /f /a #path"
for /f "delims=" %%d in ('" dir /ad /s /b | sort /R "') do rd "%%d"
popd
)
The pushd will change the current active directory to the required one. If the command is sucessful, the conditional operator && (execute next command if the previous one did not fail) will execute the rest of the code, restoring the active directory at the end.
4) robocopy
It can be used to do the clean, but not from a folder into itself.
#echo off
setlocal enableextensions disabledelayedexpansion
pushd "p:\blahblah" && (
rem Use a random temporary folder
for %%t in ("%temp%\clean_%random%%random%%random%%random%.tmp") do (
rem Select the files to keep
robocopy "." "%%~ft" /MAXAGE:8 /CREATE /s /njh /njs /nfl /nc /ns
rem Remove anything not selected
robocopy "%%~ft" "." /NOCOPY /PURGE /e /njh /njs /nfl /nc /ns
rem remove temporary folder
) & rd /s /q "%%~ft"
rem Restore previous active directory
popd
)
This code creates a replica of all the selected files (not older than 8 days) into a temporary folder, but the /CREATE switch tells robocopy to not copy the files, but to create 0 bytes files into the temporary target.
Once we have a replica with only the selected elements, the oposite operation is done, from temporary folder into work folder but requesting that no copy operation should be done (/NOCOPY), just a removal of elements not present in source (/PURGE).

Why is my bat script deleting itself when I run it

I have made a bat script as follows
cd "D:\ACT\ACTBKUP"
del /Q *.*
FORFILES /P E:\ACT_Backups /M *.zip /D +1 /C "cmd /c del #D:\ACT\ACTBKUP"
The script is supposed to delete everything in "D:\ACT\ACTBKUP" and then move the newest zip folder to that same folder from E:\ACT_Backups. When I run this script from windows server 2012 it just disappears.
thanks
In order to switch to a directory that is located on a different drive, you need to use cd /d instead of just cd. If you do not do this, the directory will not change.
When you run a script by double-clicking on it, batch considers the current directory to be the directory where the script is currently located. Since you are not using the /d option with cd, you are running del /Q *.* on the directory where the script is located.
To fix this, you have two options:
cd /d "D:\ACT\ACTBKUP"
del /Q *.*
or
del /Q "D:\ACT\ACTBKUP"
There is no option in forfiles to get just the most recent file; /D +1 will return all files with a last-modified date of today or later. In order to get the most recent file and nothing else, you will need a for /f loop:
rem /b returns just the file name and /o:d sorts the files by date
rem Since newest_file gets set for each .zip file in the directory,
rem the last file set will be the newest
for /f "delims=" %%A in ('dir /b /o:d E:\ACT_Backups\*.zip') do set newest_file=%%A
copy %newest_file% D:\ACT\ACTBKUP

Batch file to delete folder but leave a certain subfolder?

I'm trying to clear a folder of all it's contents but a certain sub-folder and its contents. My deleting works fine but I can't figure out how to exclude.
cd C:\testfolder
del * /S /Q
rmdire /S /Q "C:\testfolder"
But I do not want to delete the folder C:\testfolder\subf. How can I do this?
If you are using at least windows vista (robocopy command is used), this should do the job
#echo off
setlocal enableextensions disabledelayedexpansion
rem Create a temporary empty folder
set "tempFolder=%temp%\%~nx0.%random%%random%%random%.tmp"
md "%tempFolder%" >nul 2>nul
rem Purge from target folder anything not in the empty source folder,
rem but exclude the indicated folder
robocopy "%tempFolder%" "c:\testfolder" /nocopy /purge /xd "c:\testfolder\subfolder"
rem Cleanup
rmdir "%tempFolder%" /s /q >nul 2>nul
If you mean you want to delete all files but not the subfolder you can just use the following
cd C:\testfolder
del *.* /S /Q
This will delete any files in the "testfolder" and any files in the subfolders but will leave the subfolder there.

Resources