I want to create .bat file which allow me to delete all folder of one directory (C:\Test), except the last created folder (the folder which is the most recent in time). It's easy to me to delete all folder of one directory but try to find the most recent it's not.
for /f "skip=1 delims=" %%a in ('dir /b /ad /tc /o-d "c:\test"') do echo rmdir /s /q "c:\test\%%a"
Sort the list of directories in creation time descending, skip the first one, remove the rest.
rmdir commands are echoed to console. If output is correct, remove the echo command.
To use it from command line, replace all %% with %
Related
The folder D:\Backup contains following subfolders listed here with name (left) and last modification date (right) as displayed in Windows Explorer:
20171113.224424 15.11.2017 17:24
20171113.224421 16.11.2017 15:26
20171113.224412 16.11.2017 15:33
20171112.424424 16.11.2017 15:33
20171112.224424 16.11.2017 15:33
20171112.221424 16.11.2017 15:34
20171111.224428 16.11.2017 15:34
20171111.224427 16.11.2017 15:35
20171111.224424 16.11.2017 15:34
I need a batch script to check if there are more than two folders with same date string with always 8 digits left to . in folder name like 20171113.224424, 20171113.224421 and 20171113.224412.
The batch file should keep the newest two folders with same date string and delete all other older folders with using the folder creation date instead of last modification date.
For the example above with creation date being equal the last modification date the folders to delete are:
20171113.224424
20171112.224424
20171111.224424
When two folders have the same creation date, the one with lower number after the dot should be deleted if that is possible.
The remaining folders are:
20171113.224421
20171113.224412
20171112.424424
20171112.221424
20171111.224428
20171111.224427
I tried a lot of codes, but I don't post them all here.
I have code which list all folders in directory, but can't find the method to group the folders with same first 8 letters:
#echo off
set back=%cd%
for /d %%i in (d:\backup\*) do (
cd "%%i"
echo current directory:
cd
pause
)
cd %back%
I wrote code to skip last 10 lines if there a regular grouping and delete the folders that I don't need as described above:
#echo off
for /F "skip=10 delims=" %%I in ('dir "d:\backup\*" /AD /B /O-N 2^>nul') do rd /Q /S "d:\backup\%%I"
A batch file for this task would be:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "BackupFolder=D:\backup"
set "LastDate="
for /F "delims=." %%I in ('dir "%BackupFolder%\????????.*" /AD /B /ON 2^>nul') do (
if not "!LastDate!" == "%%I" (
for /F "skip=2 delims=" %%D in ('dir "%BackupFolder%\%%I.*" /AD /B /O-D-N /TC') do rd /Q /S "%BackupFolder%\%%D"
set "LastDate=%%I"
)
)
endlocal
The first, outer FOR executes in a separate command process started with cmd /c in background the DIR command line specified in first parenthesis and captures everything output by DIR to handle STDOUT for processing it later line by line.
The used DIR command outputs
only directories matching wildcard pattern ????????.* because of /AD (attribute directory)
with only their names without path because of /B (bare format)
sorted by name because of /ON (ordered by name).
It is possible that the backup folder currently contains no folder matching this pattern. In this case DIR would output an error message to handle STDERR which would be confusing because of containing file instead of directory. This possible error message is redirected to device NUL to suppress it.
Read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the DIR command line with using a separate command process started in background.
Outer FOR processes the captured lines with ignoring empty lines and lines starting with a semicolon. Such lines do not exist here, so no problem. Each (other) line is split up into two strings using . as delimiter. Only the first string left to first . of each line is assigned to loop variable I which is used in the command lines executed next.
It is important here to use command DIR to get a directory list processed by FOR not being modified during loop execution instead of using for /D which would read next directory name directly from file system on each iteration of the loop. The list of directories changes during loop execution. On using for /D it could happen that some directories are skipped because of directory list changes while processing the directories.
The IF condition makes a simple case-sensitive string comparison using delayed environment variable expansion to compare the date string of previous processed folder(s) with the current folder. Only on difference between date of last processed folder(s) and date of current folder the inner loop is executed. This IF condition is just for making the folder deletion process a little bit faster.
It is no problem here to use delayed environment environment variable expansion as no folder in backup folder contains an exclamation mark in folder name.
The second, inner FOR loop runs also command DIR to get a list of directories with the date string of current folder with just their names, but this time first reverse ordered by creation date and second reverse ordered by name in case of two or more folders have same creation date because of /O-D-N (ordered reverse by date and next reverse by name) and /TC (time: creation). Reverse date order means newest directory is output first and oldest is output last.
The inner FOR loop processes the captured lines output by DIR with skipping the first two lines which means ignoring the two newest folders. The other lines are processed without splitting the line up because of delims= (empty delimiter list) and therefore the complete folder name as output by DIR is assigned to loop variable D.
The command RD deletes the folder of which name is hold in loop variable D quietly because of /Q with all files and subfolders because of /S.
Then the date string of current folder is assigned to environment variable LastDate to skip all folders in directory list of outer FOR with same date string.
It would be also possible to use a single command line without usage of delayed environment variable expansion being a bit slower which would also work for folders with ! in name.
#for /F "delims=." %%I in ('dir "D:\backup\????????.*" /AD /B /ON 2^>nul') do #for /F "skip=2 delims=" %%D in ('dir "D:\backup\%%I.*" /AD /B /O-D-N /TC') do #rd /Q /S "D:\backup\%%D"
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.
dir /?
echo /?
endlocal /?
for /?
if /?
rd /?
set /?
setlocal /?
Update:
Enhanced version logging the names of all files with full path before deletion of a backup directory.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "BackupFolder=D:\backup"
set "LastDate="
set "LogFile=%BackupFolder%\DeletedFiles.log"
for /F "delims=." %%I in ('dir "%BackupFolder%\????????.*" /AD /B /ON 2^>nul') do (
if not "!LastDate!" == "%%I" (
for /F "skip=2 delims=" %%D in ('dir "%BackupFolder%\%%I.*" /AD /B /O-D-N /TC') do (
dir "%BackupFolder%\%%D" /A-D /B /ON /S >>"%LogFile%" 2>nul
rd /Q /S "%BackupFolder%\%%D"
)
set "LastDate=%%I"
)
)
endlocal
Single command line version:
#for /F "delims=." %%I in ('dir "D:\backup\????????.*" /AD /B /ON 2^>nul') do #for /F "skip=2 delims=" %%D in ('dir "D:\backup\%%I.*" /AD /B /O-D-N /TC') do #dir "D:\backup\%%D" /A-D /B /ON /S >>"D:\backup\DeletedFiles.log" 2>nul & rd /Q /S "D:\backup\%%D"
I need to copy a folder matching a wildcard, for instance FOLDER_*. That folder will be in the presence of other files, so I need the command to segregate it from everything else. Also, the command needs to recursively search through the directory, and return only the FOLDER that matches the wildcard, with its contents intact. Then it needs to copy it to another folder. Any ideas? I've tried quite a few variants - here is the last thing I tried.
for /D /R %%f in (FOLDER_*) do xcopy %%f %~dp0\TestResults
Next code snippet should copy all found FOLDER_* folders including their subfolders but omits all their parent folder(s) like upfolder\ in upfolder\FOLDER_* (however could be improved to include it, of course).
for /F loop against dir /b /s /ad (a static list of subfolders) is used instead of for /D /R as the option /d /r is undocumented.
Pay your attention to recursion like FOLDER_main\FOLDER_sub1\FOLDER_sub11 etc.
Operational mkdir and xcopy commands are merely echoed for debugging purposes only:
#echo OFF
for /F "delims=" %%f in ('dir /B /S /AD FOLDER_*') do (
echo mkdir "%~dp0\TestResults\%%~nxf" 2>NUL
echo xcopy /S /E /C "%%~ff" "%~dp0\TestResults\%%~nxf\"
)
Consider adding more switches to xcopy, for instance
/H Copies hidden and system files also.
/R Overwrites read-only files.
/Y Suppresses prompting to confirm you want to overwrite an existing destination file.
I am trying to copy all .ini files from the Windows folder into a new folder I have already created. I need this to loop through for all users. Here is what I have but it only works for the last user, not each of them. This is a batch file.
for /r %%f in ("D:\Home\*.*\windows") do
set dir="%%d
for /r "%dir%\windows\" %%f in (*.ini) do (
copy %%f "%dir%\temp_ini"
))
pause
Please help :/ Thank you
You've got a few problems -- unterminated quote on the second line, not delaying the expansion of %dir% (and indeed, setting %dir% is unnecessary, anyway), illogical use of for /r in the first line, trying to recycle %%f in nested loops, and your *.* wildcard in the first line will only match directories containing a dot. You should also make sure the temp_ini directory is outside the scope of your search for ini files; otherwise, Windows will attempt to copy the contents of temp_ini\*.ini into itself recursively. Try this instead:
for /d %%I in ("D:\Home\*") do (
rem // create directory if not exist
if not exist "%%~I\temp_ini" md "%%~I\temp_ini"
rem // capture the output of dir /s /b
for /F "delims=" %%x in (
'dir /s /b "%%~fI\Windows\*.ini" 2^>NUL'
) do copy /y "%%~fx" "%%~I\temp_ini\"
)
pause
I have a file structure of images that is fairly flat although quite large (only goes 3-4 levels deep). In this structure I want to delete all folders that end with '.files' (no quotes).
Note that the files I want to delete are hidden.
I saw a relevant question (linked below) that suggested the following batch file (except using '_svn')
Command line tool to delete folder with a specified name recursively in Windows?
for /d /r . %d in (_svn) do #if exist "%d" rd /s/q "%d"
but it didnt work quite right for me. I got the following error when running at the directory I want to start:
d" rd /s/q "d" was unexpected at this time.
So to be clear, I'm looking for a command that I can put into a batch file which I can cd to my desired directory, run the command, and delete directories beneath the current directory that end in '.files'
Any suggestions?
for /f %a in ('dir C:\yourdir\*.files /b /s /a:hd') do rd /s /q "%a"
or if running it from a batch file use 2 %'s
for /f %%a in ('dir C:\yourdir\*.files /b /s /a:hd') do rd /s /q "%%a"
I'm looking to write a short batch script that will delete all files within a set of directories. More specifically, suppose I have the top directory "workspace" and it contains several directories beginning with the sting "project" (e.g. project-something, project-another). Then each of these "project" directories contain a "model" directory. I want to have the script empty each of these model directories.
I know this is doesn't work, but I looking for something along the lines of
del project*\model\*
But I know that the * after project will not select all directories starting with project then proceed into the model directories to clear them. What would be a correct way to go about doing this?
Thank you for your time!
Put this into a .bat file and run.
#echo off
for /F "usebackq delims=" %%F in (`dir /ad /s /b model`) do (
del /s /q "%%F"
echo Removed "%%F"
)
pause