batch file to Delete X days old files exclude few files - batch-file

I want to delete X days old files from a directory but want to exclude a specific file (*exception). I am using below command, but seems it is not working for me.
for /f "delims=" %%a in ('forfiles /p "%userprofile%\.." /d -180 /c "cmd /c if #isdir==TRUE echo #file"^|findstr /vig:"%userprofile%\exception.txt"') do echo rd /s /q "%%~a"

Instead of using ForFiles you could use RoboCopy:
#For /F "Tokens=*" %%A In ('RoboCopy "%UserProfile%\.." Null /L /MinAge:180 /NC /NDL /NJH /NJS /NP /NS /XF exception*') Do #Del "%%A"
Enter RoboCopy /? at the Command Prompt for its usage information.
After re-reading your question, together with your code, it isn't clear whether you're wanting to exclude files named, exception*, which is what my answer above does, or to exclude files as listed inside a file named exception.txt. If it's the latter then you'd need to build a string of your exclusions first to append to the /XF list.
If your file only contains a few relatively short exclusion masks then you may be able to do it like this:
#Echo Off
Set "EX="
For /F "UseBackQ Delims=" %%A In ("%UserProfile%\exception.txt") Do (
If Not Defined EX (Set "EX=%%A ") Else Call Set "EX=%%EX%%%%A ")
For /F "Tokens=*" %%A In ('RoboCopy "%UserProfile%\.." Null /L /MinAge:180 /NC /NDL /NJH /NJS /NP /NS /XF %EX%') Do Del "%%A"

Related

Batch zipping multiple files in single directory

I need to make batch script, which will work this way:
There is a folder with one hundred files. I need to make a script which is zipping every 4 files into single archive. Then all created archives must be zipped into one, big archive file. That must be all done by one script.
I tried to make it, but I haven't idea how to make it this way.
This is what I wrote first:
#ECHO ON
SET SourceDir=C:\Users\Ridaan\Documents\sobol
SET DestDir=C:\folder\Destination
CD /D "C:\Program Files\7-Zip"
FOR /F "TOKENS=*" %%F IN ('DIR /B /A-D "%SourceDir%"') DO (
7z.exe a "%DestDir%\%%~NF.zip" "%SourceDir%\%%~NXF"
)
EXIT
And second:
#echo off
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
robocopy C:\folder\Destination /COPY:DAT /V /XO /NJH /NP /R:1000 /W:10
7z u -mx9 "C:\folder\End.7z" "C:\folder\Destination"
rmdir C:\folder\End\ /Q /S
:END
pause
Just to give you an idea of counting files and
calculating the int of count/4 for the zip number
the modulus%4 for the file number (0..3) to determine if it's a new zip to create or to append to the zip.
:: Q:\Test\2018\11\11\SO_53251220.cmd
#Echo off&SetLocal EnableExtensions EnableDelayedExpansion
set Cnt=0
Set "SrcDir=X:\Your\Path"
For /F "delims=" %%A in ('Dir /B/A-D "%SrcDir%\*"') do (
Set /A "File=Cnt%%4,Zip=Cnt/4,Cnt+=1"
Echo Cnt=!Cnt! File=!File! Zip=!Zip! File=%%A
)

find path of latest file using batch command

I have files named file.txt in multiple subfolders in my folder. I want to get the path of the latest file.txt
FOR /r %%i IN ('DIR file.txt /B /O:-D') DO SET a=%%i
echo Most recent subfolder: %a%
gives latest created folder having file.txt whereas I want the folder which has latest file.txt
#echo off
setlocal enableextensions disabledelayedexpansion
for /f "tokens=1,2,*" %%a in ('
robocopy . . file.txt /l /nocopy /is /s /nc /ns /ts /ndl /njh /njs
^| sort /r 2^> nul
^| cmd /v /q /c "set /p .=&echo(^!.^!"
') do (
echo File found : %%c
echo File timestamp (UTC^) : %%a %%b
echo Folder of file : %%~dpc
)
This will use the robocopy command to enumerate all the file.txt files under the current active directory, without copying anything but generating a list of all matching files with a yyyy/mm/dd hh:nn:ss utc timestamp. Then the list is sorted on the timestamp in descending order and only the first line in the output readed and echoed to be processed by the for /f tokenizer and retrieve the date, time and file with full path.
If only the folder is required and the list of files is not very large, a simplified version could be
#echo off
setlocal enableextensions disabledelayedexpansion
for /f "tokens=1,2,*" %%a in ('
robocopy . . file.txt /l /nocopy /is /s /nc /ns /ts /ndl /njh /njs
^| sort /r
') do set "lastFolder=%%~dpc" & goto :done
:done
echo Last folder : %lastFolder%
Almost the same, but instead of including a filter in the list generation to only retrieve the first line (required if the list of files is very large), here the for /f will retrieve the full list but after the first element is processed we jump out of the loop to the indicated label.

File Retention Script

I have a directory that has a 10 sub-directories. Each of these holds different .bak files. I'm trying to create a script that will check to see if X number of files are there and if the number of files exceeds X, it deletes the oldest file. In other words, I want 20 iterations of a .bak file. When the 21st one shows up, I want the batch file to delete the oldest one.
Is this possible?
If so, can I create a single script that looks in all the sub-directories?
Thanks in advance.
Two options included. The first one will leave %maxFiles% bak files under each of the folders. The second one (windows Vista or later OS is required as robocopy is used to obtain the sorted list of files) will leave %maxFiles% in total
#echo off
setlocal enableextensions disabledelayedexpansion
set "rootFolder=%cd%"
set "maxFiles=20"
rem Option 1 - Keep %maxFiles% inside each of the subfolders
for /d /r "%rootFolder%" %%z in (*) do for /f "skip=%maxFiles% delims=" %%a in (
'dir /tc /o-d /a-d /b "%%~fz\*.bak" 2^>nul'
) do echo del "%%~fz\%%~nxa"
echo ------------------------------
rem Option 2 - Keep %maxFiles% in total under all the subfolders
for /f "skip=%maxFiles% tokens=2,*" %%a in ('
robocopy "%rootFolder%" "%rootFolder%" *.bak /l /nocopy /is /s /njh /njs /ndl /nc /ns /ts
^| findstr /v /r /e /i /c:"%rootFolder:\=\\%\\[^\\]*"
^| sort /r
') do echo del "%%b"
del commands are only echoed to console. If the output is correct, remove the echo command to remove the files
assumes that you want to check the number of files from the parent directory.Can be done also for each sub-directory.
#echo off
setlocal
set "max_number_files=20"
set "parrent_dir=c:\whatever_you_need"
set "extension=.bak"
pushd "%parrent_dir%"
set "count=0"
setlocal enableDelayedExpansion
for /f "delims=" %%a in ('dir /s /b /a:-d /o:-d /t:c *%extension%') do (
set /a count=count+1
if 1!count! GTR 1!max_number_files! (
rem --- remove the echo to activate deletion
echo del /q /f "%%~a"
)
)
popd
endlocal
endlocal
This will check each folder under d:\base\folder and if there are more than 20 *.bak files it will remove the oldest ones so only 20 *.bak file remain, in each folder.
Test it on some sample folders.
#echo off
for /d /r "d:\base\folder" %%a in (*) do (
pushd "%%a"
for /f "skip=20 delims=" %%b in ('dir /b /a-d /o:-d *.bak ') do del "%%b"
popd
)

batch findstr to certain depth of subfolders

I had the below code for searching through sub directories for 2 exe files:
#echo off & setLocal EnableDELAYedeXpansion
for %%d in (c) do if exist %%d: (
for /f "delims=" %%a in ('dir/b/s/x %%d:\autolog.exe %%d:\autorun.exe 2^>nul ^| findstr /V /C:".*\.*\.*\.*\.*\.*\.*\.*\.*" /C:".*\.*\.*\.*\.*\.*\.*\.*" /C:".*\.*\.*\.*\.*\.*\.*" /C:".*\.*\.*\.*\.*\.*" /C:".*\.*\.*\.*\*"') do (
set var=%%a;!var!
))
echo %1,!var!, >>C:\test.txt
exit
While it works search for all subfolder (by using /s), I would like to have result returns only if it is within 4 subfolder level (e.g. c:\sf1\sf2\sf3\autorun.exe should be a valid result, while c:\sf1\sf2\sf3\sf4\autorun.exe and any finding further down the tree should be opt out and not returning as a result).
I use all wildcard combination (* | .| .*) along with "\V" in attempt to achieve it but failed. Why does it won't work or if there are other smarter way doing it?
Thanks in advance
Heres is a sample to limit to fourth folder level, using regular expressions in the findstr terms:
#echo off
for /f "delims=" %%a in ('dir /ad /b /s ^| findstr \\.*\\.*\\.*\\ ^| findstr /v \\.*\\.*\\.*\\.*\\') do echo %%a
pause
I was inspired by this answer. ROBOCOPY is available since Vista, and it is a robust utility that does more than copying files.
e.g. The /L switch prevents it from copying; while /LEV allows you to copy only the top N levels of root, which eliminates one FINDSTR.
Golfed
#echo off
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=*" %%F in ('
ROBOCOPY "C:\." "C:\." autolog.exe autorun.exe /S /LEV:4 /IS /L /NS /NC /NDL /NJH /NJS^|FINDSTR \\.*\\.*\\.*\\
') do set "var=%%~fF;!var!"
echo %1,!var!,>>C:\test.txt
Formatted
#echo off
====SETLOCAL EnableDelayedExpansion EnableExtensions
set "list="
set ^"FORCMD=^
%__APPDIR__%ROBOCOPY.EXE C:\. C:\. autolog.exe autorun.exe^
/S %=non-empty Subdirectories=%^
/LEV:4 %=MAX 4 LEVels=%^
/IS %=Include Same files=%^
/L %=List only (don't copy)=%^
/NS %=No Size=%^
/NC %=No Class=%^
/NDL %=No Directory List=%^
/NJH %=No Job Header=%^
/NJS %=No Job Summary=%^
|%__APPDIR__%FINDSTR.EXE \\.*\\.*\\.*\\%=MIN 4 LEVels=%" It's convenient to use delayed expansion
FOR /F "tokens=*" %%F in ('!FORCMD!') do set "var=%%~fF;!var!"
::Due to weird expansion rules
::if VAR was undefined, it is set to '~,-1'
if DEFINED var set "var=!var:~,-1!" Remove trailing ;
>>"C:\test.txt" echo(%1,!var!,

Finding the newest file in a directory

I am a complete novice in batch programming but have found some great scripts in here that I tried modifying. I need the info on the last file modified in a directory. The script below gives me a file with info about file name and modification time. It searches through subdirectories too but seems to get stuck in a subdirectory instead of finding the newer file in the parent directory. I am not sure what could be wrong (as I only partly understand the code). Any suggestions from you smart guys in here?
Thanks in advance!
#echo off
setlocal
set srcDir=C:\Test
set lastmod=
pushd "%srcDir%"
for /f "tokens=*" %%a in ('dir *. * /b /od /s /a-d 2^>NUL') do set lastmod=%%a
if "%lastmod%"=="" echo Could not locate files.&goto :eof
for /d %%a in ("%lastmod%") do echo "%lastmod%", Modified date: %%~ta>"C:\Test\Details.txt"
This uses robocopy so it will only work on windows Vista and later. For it to work on XP you will need to get a copy of robocopy from a later OS or from resource kit.
No copy operation will really be made, but it will allow to retrieve a recursive file list with an adequated file stamp that can be sorted to find latest file.
#echo off
setlocal enableextensions disabledelayedexpansion
set "folder=%cd%"
for /f "tokens=2,*" %%a in (
'robocopy "%folder%" "%folder%" "*" /s /is /nocopy /nc /ns /ts /fp /np /ndl /njh /njs /xjd /r:0 /w:0 /l ^| sort /r '
) do ( set "latest=%%b" & goto :done )
:done
for %%f in ("%latest%") do echo(%%~tf %%~ff

Resources