I have this script:
forfiles /p "C:\Hello" /m *.* /s /d -5 /c "cmd /c if /i not #path==C:\Hello\Dontdelete del #file"
I'm trying to delete every file older than 5 days in C:\Hello except for files that are in C:\Hello\Dontdelete or any directory within this path.
Currently everything is getting deleted when I use the above script.
Thanks!
The fundamental problem is that #path is the full pathname - including the filename+extension, and quoted and #file is the filename+extension, also quoted. In consequence, the if statement as constructed can't be manipulated to work as anticipated.
Here's a way to get it working (I've made a few changes to suit my system which should be easy to manipulate to suit yours)
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
forfiles /p "%sourcedir%" /m *.* /s /d -6 /c "cmd /c call %cd%\selectdel #PATH"
GOTO :EOF
I set up selectdel as a batch in my current directory. No doubt it would be fine on the path, or simply forced as I have with the %cd%\.
selectdel.bat
#echo off
setlocal
if /i not "%~dp1"=="%sourcedir%\Dontdelete\" echo DEL %1
GOTO :eof
Obviously, I've simply echoed the del command - in case of accidents...
I do not know much about it, but I think you should make a lopping for every 5 days, the script did a check to see if there are files in the folder C :/ Hello, if yes, the script clears, if not, it does nothing. Search about it.
Related
This problem is from the scheduler task, batch program, or the files in a folder that I want to delete it using the batch program?
and this is the batch program:
forfiles /p "D:\nameOfFolder" /s /m *.* /d -7 /c "cmd /c del #path"
Replace /M *.* by /M * to even include files without extension, because forfiles treats wildcards differently than most other commands. /M * may even be omitted since this is the default setting anyway.
Regard that forfiles iterates both files and directories, so you need to exclude the latter, because del may try to delete its contents then. Therefore, implement a condition based on the forfiles-specific variable #isdir.
forfiles /S /P "D:\nameOfFolder" /M * /D -7 /C "cmd /D /C if #isdir==FALSE del #path"
As a side note, never append a trailing backslash to a (quoted) path, because something like /P "D:\" would let the command fail since \" constitutes an escaped quotation mark for forfiles, ruining the command line. You may however specify /P "D:\.".
Are you sure you even have such files?
I tried the following (very similar) command:
forfiles /p "C:\Temp_Folder" /s /m . /d -7 /c "cmd /c echo #path"
ERROR: No files found with the specified search criteria.
One thing I noticed, is that the name of the directory should not end with a backslash:
forfiles /p "C:\Temp_Folder" is working fine.
forfiles /p "C:\Temp_Folder\" is not working.
. on its own is not a valid searchmask to supply to /m.
You ned to use *.* (all) *.ext (the supplied extension) *string*.* (files with names containing the string).
? is also supported as a searchmask to match any character. example: *.?a* would match any file with an extension type with a as the second character
I'm writing a batch file for Windows 7.
I currently have a code that deletes old backups from our masters folders within our site management folders. This is the code:
for /d %%A in ("Y:\*.*") do del /s /q /f "%%A\masters\*.bak"
However I need to code it to only delete things that are older than 3 years, which would be this code:
forfiles /P "Y:\" /S /D -1096 /M *.bak /C "cmd /C del #path"
However I need what is in the top code so that I can delete all *.bak files from the masters folders that exist within our 173 site management folders. I'm ripping my hair out figuring this out. I can't have it deleting *.bak files from our other folders.
I've tried combining the code, but below command line in batch file does not work as expected:
forfiles /S /D -1096 /M *.bak /C "cmd /C for /d %%A in ("Y:\*.*") do del /s /q /f "%%A\masters\*.bak"
How to delete all *.bak files older than 3 years anywhere in directory tree if second directory in file path is masters and keep all other *.bak files being newer or in a directory where second directory in file path is not masters?
Create first a batch file C:\Temp\DeleteBackup.bat with the following commands:
#echo off
set "BackupFileName=%~1"
if not "%BackupFileName:\masters\=%" == "%BackupFileName%" ECHO del "%BackupFileName%"
This batch code checks if the file name with full path and file extension contains anywhere \masters\ by removing this string case-insensitive from left argument of string comparison.
If the remaining string is not equal the unmodified file name string because of containing \masters\ in path, the IF condition is true and the backup file would be deleted if there would not be command ECHO which results in just displaying the DEL command line.
For example the complete list of backup files is:
Y:\masters\Level2\Level3\Level4\Level5\Test1.bak
Y:\Folder2\masters\Level3\Test2.bak
Y:\Folder3\Level2\masters\Level4\Test3.bak
Y:\Folder4\Level2\Level3\Level4\Level5\Test4.bak
Y:\Folder5\Level2\Test5.bak
Y:\Folder6\Level2\Level3\Level4\Level5\Level6\Test6.bak
Y:\Folder7\masters\Test7.bak
The files deleted would be:
Y:\masters\Level2\Level3\Level4\Level5\Test1.bak
Y:\Folder2\masters\Level3\Test2.bak
Y:\Folder3\Level2\masters\Level4\Test3.bak
Y:\Folder7\masters\Test7.bak
And the files remaining would be:
Y:\Folder4\Level2\Level3\Level4\Level5\Test4.bak
Y:\Folder5\Level2\Test5.bak
Y:\Folder6\Level2\Level3\Level4\Level5\Level6\Test6.bak
Then use in your batch file:
forfiles /P "Y:\" /S /D -1096 /M *.bak /C "C:\Temp\DeleteBackup.bat #PATH"
It is of course possible to modify DeleteBackup.bat to check if directory in second directory hierarchy level is masters.
#echo off
for /F "tokens=3 delims=\" %%I in ("%~1") do if /I "%%I" == "masters" ECHO del "%~1"
This code would delete from the complete list above the files:
Y:\Folder2\masters\Level3\Test2.bak
Y:\Folder7\masters\Test7.bak
And the files remaining would be:
Y:\masters\Level2\Level3\Level4\Level5\Test1.bak
Y:\Folder3\Level2\masters\Level4\Test3.bak
Y:\Folder4\Level2\Level3\Level4\Level5\Test4.bak
Y:\Folder5\Level2\Test5.bak
Y:\Folder6\Level2\Level3\Level4\Level5\Level6\Test6.bak
Robert Chizmadia Jr. asked in an already deleted comment:
Is it possible to use GOTO instead of calling another batch file on FORFILES command line?
The answer on this additional question:
FORFILES is not an internal command of cmd.exe like FOR. It is a console application stored in directory %SystemRoot%\System32 if used version of Windows has it pre-installed at all.
The command to execute as specified after FORFILES option /C must be an executable or script. That is the reason why cmd /C is always used when an internal command of Windows command interpreter cmd.exe like DEL should be executed by FORFILES whereby the really complete command would be %SystemRoot%\System32\cmd.exe /C.
So it is not possible to use a command like GOTO in FORFILES command as there is no executable or script with name GOTO.
Also GOTO in a FOR loop exits the loop and therefore interpreting of command lines of batch files continues on another position in batch file.
However, it is possible to use the same batch file for the file path evaluation and backup file deletion as used to run FORFILES command.
Example 1 with batch file not expecting any parameter for default operation:
#echo off
if not "%~1" == "" (
for /F "tokens=3 delims=\" %%I in ("%~1") do if /I "%%I" == "masters" ECHO del "%~1"
goto :EOF
)
%SystemRoot%\System32\forfiles.exe /P "Y:\" /S /D -1096 /M *.bak /C "%~f0 #PATH"
If this batch file is executed with an argument, it runs the FOR loop written to check if second directory in file path is masters and delete this file in this case after removing ECHO. Otherwise on starting the batch file without any parameter the batch file runs the FORFILES executable.
Example 2 with batch file expecting 1 or more parameters for default operation:
#echo off
if "%~1" == "#Delete:Backup#" (
for /F "tokens=3 delims=\" %%I in ("%~2") do if /I "%%I" == "masters" ECHO del "%~2"
goto :EOF
)
rem Other commands processing the parameters.
%SystemRoot%\System32\forfiles.exe /P "Y:\" /S /D -1096 /M *.bak /C "%~f0 #Delete:Backup# #PATH"
rem More commands executed after the deletion of the backup files.
This is nearly the same as example 1 with the difference that if first parameter used on running the batch file is case-sensitive the string #Delete:Backup#, the batch file expects as second parameter the name of a backup file with full path being deleted if second directory in file path is masters.
Like in all batch code examples the command ECHO must be removed before del command also in this code example to really execute the deletion of the backup files.
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 /?
forfiles /?
goto /?
if /?
set /?
Im trying to write a script for keep clear my desktop. I want to delete all files and directories except the shortcuts.I use Windows 10. My batch code is the following:
#echo off
COLOR 0E
cd "C:/Users/DA/Desktop"
FORFILES /S /C "if #ext!=lnk del /F /Q /S"
rd /S /Q "."
pause
exit
Maybe it is a dumb error, but Im a newbie in Windows command line. Thanks in advance.
There are several issues in your code:
You must precede the command line after the /C switch of forfiles with cmd /C, because you are using internal console commands (if, del). If you omit cmd /C, forfiles tries to find a program file named if, which does not exist.
There is no comparison operator != for the if statement. You mean not equal, so you need to state if not <expression1>==<expression2> instead.
The #ext variable expands to the file extension enclosed in quotation marks, so you need to state them around lnk also. Since the "" are in the quoted command line behind forfiles /C, you need to escape them like \" in order to establish literal " characters.
You forgot to specify what to delete at the del command.
The switches /S of forfiles and also del mean to process also items in sub-directories, but I assume you do not want that, because you want to clean up your Desktop directory.
There is the rd command, so I assume you want to remove any directories from the Desktop either. However, rd /S /Q "." tries to remove the entire Desktop directory (which will fail as your batch file changes to that directory by cd). I would put the rd command into the forfiles command line as well, because there is the possibility to check whether or not the currently iterated item is a file or a directory (forfiles features the #isdir variable for that purpose).
The cd command works only if you are running the batch file from the same drive where the Desktop directory is located (unless you provide the /D switch). I would go for the pushd command, which changes to the Desktop directory temporarily, until a popd command is there.
Instead of hard-coding the location of the Desktop directory, I would use the built-in environment variable %USERPROFILE%, which points to the user profile directory of the currently logged on user, where the Desktop directory is located in.
The exit command without the /B switch does not only end the batch file, it also terminates the command interpreter instance the batch file is running in. This does not matter when you run the batch file by double-clicking, but it does matter when you execute it within command prompt.
Here is the corrected and improved code:
#echo off
title Clean Up Desktop & rem // (this is the window title, just for fun)
color 0E
pushd "%USERPROFILE%\Desktop" || exit /B 1 & rem // (the command after `||` runs if `pushd` fails, when the dir. is not found)
rem /* Here you can see how to distinguish between files and directories;
rem files are deleted with `del`, directories are removed with `rd`.
rem The upper-case `ECHO`s are there for testing purposes only;
rem remove them as soon as you actually want to delete any items: */
forfiles /C "cmd /C if #isdir==FALSE (if /I not #ext==\"lnk\" ECHO del /F /Q #relpath) else ECHO rd /S /Q #relpath"
pause
popd & rem // (this restores the previous working directory)
exit /B & rem // (this quits the batch file only; not necessary at the end of the script)
You can try something like that :
#echo off
COLOR 0E
CD /D "%userprofile%\Desktop"
Rem To delete folders
for /f "delims=" %%a in ('Dir /b /AD ^| find /v "lnk"') do echo rd /S /Q "%%a"
pause
Rem To Delete files
for /f "delims=" %%a in ('Dir /b ^| find /v "lnk"') do echo del /F /Q /S "%%a"
pause
exit
NB: When your execution is OK, just get rid of echo command
You can use the for and if commands to accomplish this:
#echo off
COLOR 0E
cd C:/Users/DA/Desktop
for /d %x in (*) do #rd /s /q "%x"
for %i in (*) do if not %i == *.lnk del "%i"
pause
Pretty simple and works great.
Make sure that %i and %x are in "".
I'm using a batch file now to delete all files ending in .snp that are older than 180 days. The code below works to delete all files ending in .snp under the root folder
C:\Program Files\Snapshots
But I recently discovered that within the Snapshots folder there are folders organized by date
"1-10-2014, 12-20-2014, 10-15-2014 etc.."
and that the below line of code doesn't work to recursively search through each directory and is therefore not deleting.
What changes should I make to this code to have it recursively search through folders within a root folder and delete files that are greater than 180 days?
forfiles /M *.snp /P "C:\Program Files\Snapshots" /S /D -180 /C "cmd /c del /F /Q #path"
Without the /D (Date) it workes for sub-folders
forfiles /M *.txt /P "C:\hlpme" /S /C "cmd /c del /f /q #path
but you obviously want the date to be there
then in CMD
forfiles /D -180 /M *.txt /P "C:\hlpme" /S /C "cmd /c del /f /q #path
The /D before the Pathname selects all files that have been changed more than 180 days ago
The best option for highest reliability is to combine the strengths of the For command with the FORFILES commands to allow each one to do what they do best.
Set str_Ext=*.snp
Set int_Age=-180
For /R "%~dp0" %%D IN (.) DO (
For /F "usebackq tokens=*" %%F IN (`FORFILES /P "%%~D" /m %str_Ext% /D %int_Age% 2^>nul`) DO (
Call :s_Del_File "%%~D" "%%~F"
)
)
Goto :EOF
:s_Del_File
Set "str_DIR=%~1"
Set "str_FIL=%~2"
Set "str_DIR=%str_DIR:~0,-1%"
DEL /F/Q/A "%str_DIR%%str_FIL%"
Goto :EOF
Within the second FOR command, the backquote (~ key) contains the FORFILES command and uses the console output to call a batch subroutine to delete the specified file.
Spaces in folder and file names will not slow this beast down, and the double quotes ["] around the Set commands will allow the process to work with folders and files that have parentheses in them or other exotic, but allowable characters.
I am trying to write a script that deletes items in the TEMP folder(s) in Windows 7. I only want it to delete files that are 30 days or older. I'm doing testing in a folder which I have set up in the system's environmental variables as TESTTEMP.
I have the script as follows:
forfiles /p %TESTTEMP% /s /d -30 /c "cmd /c IF #ISDIR==FALSE del #FILE /q"
forfiles /p %TESTTEMP% /s /c "cmd /c IF #ISDIR==TRUE rmdir #FILE"
My logic behind this is that the process should first delete all files within the TESTTEMP directory if the file is older than 30 days, and to check in all the subdirectories. Then I check through the remaining files and if it is an empty directory, remove it.
This script works perfectly - all the files I want to delete are deleted, and those that are supposed to remain, remain. However, I noticed that when I run this batch file, I get the error The system cannot find the file specified. I believe it's having some problem with the rmdir command and not being able to find the directory it just deleted...
Is this something I should be worried about, since the script appears to do what I want it to do?
Better yet, is there a way to display which file is not being found so I can try to figure out what's happening on my own?
Thanks for any help!
(For reference, here is the folder structure before and after the batch file is run, assuming all files are older than 30 days:)
Before:
-TestTemp
-More Test
testfile1.txt
testfile2.txt
testfile3.txt
testfile1.txt
testfile2.txt
testfile3.txt
After:
-TestTemp
You can display files and folders:
forfiles /p "%TESTTEMP%" /s /c "cmd /c IF #ISDIR==TRUE echo rmdir #FILE"
forfiles /p "%TESTTEMP%" /s /d -30 /c "cmd /c IF #ISDIR==FALSE echo del #FILE /q"
If a folder is not empty then it will return a harmless error message. The 2>nul will remove the error message.
forfiles /p %TESTTEMP% /s /c "cmd /c IF #ISDIR==TRUE rmdir #FILE 2>nul"
I was getting this "The system cannot find the file specified" error too, but it went away when I removed the "/s" from the ForFiles call. I did not actually need the /s, but it looks like the poster here did. If you need the recursive delete and can't live with the error (or don't want to swallow it with 2>nul), maybe you could nest a non-recursive ForFiles within a recursive one? Just a thought.