I want to delete a specific directory on Windows. I use the code below. It works fine. I want to put the .bat file I made for this process in that directory. Naturally, the .bat file is also deleted. I want the .bat file to be excluded from this deletion. What should I do with the code?
Echo batch file delete folder
#RD /S /Q "D:\testfolder"
All you have to do is to lock your batch file, by opening a dummy read handle to it.
echo The batch file wont be deleted because it is locked by a dummy input redirection.
rd /s /q "D:\testfolder" 9<"%~f0"
Naturally, an error message will be shown by the rd command, because there is at-least one file in the target directory (your own batch file) which can not be deleted. You can hide that message by redirecting the standard error stream to the nul device:
rd /s /q "D:\testfolder" 9<"%~f0" 2>nul
There are several ways to achieve your task.
The method, (especially as you generally remove directories with one command, and delete files with another), is to identify the files and subdirectories separately. First identify the subdirectories and remove those, using the RD command, then delete all files except for the batch file itself, %0:
You could do that in one line using the ForFiles utility:
#%SystemRoot%\System32\forfiles.exe /P "%~dp0." /C "%SystemRoot%\System32\cmd.exe /C If #IsDir==TRUE (RD /S /Q #File) Else If /I Not #file == \"%~nx0\" Del /A /F #File"
Or you could use a For loop, with the Dir command:
#For /F Delims^=^ EOL^= %%G In ('Dir /B /A "%~dp0"') Do #If "%%~aG" GEq "d" (RD /S /Q "%%G") Else If /I Not "%%G" == "%~nx0" Del /A /F "%%G"
Please note that you can only remove/delete items for which you have the required permissions.
I would walk through the items in the folder whose contents you want to delete, remove one after another, except its name equals the name of the batch file:
rem // Change into target directory:
pushd "%~dp0." && (
rem /* Loop through immediate children of the target directory, regarding even
rem hidden and system items; to ignore such (replace `/A` by `/A:-H-S`): */
for /F "delims= eol=|" %%I in ('dir /B /A "*"') do (
rem // Check name of current item against name of this batch script:
if /I not "%%~nxI"=="%~nx0" (
rem /* Assume the current item is a sub-directory first (remove by `rd`);
rem when removal fails, try to delete it as a file (done by `del`): */
rd /S /Q "%%I" 2> nul || del /A /F "%%I"
)
)
rem // Return from target directory:
popd
)
Related
I have the following file and folder structure (using real names):
Carabidae/Pterostichinae/FolderNameXXX/dor/StackXXX/files.tif
My problem is that I need to get one specific file, PM*.*, from the StackXXX folders into their respective /dor parent folders. The StackXXX folder can then be deleted.
There are hundreds of FolderName. Ideally I would like a batch file I can run from the Carabidae folder.
This needs to be a batch file because there will be new FolderNames added constantly.
After a lot of searching, I found a semi-working solution from this StackOverflow answer:
for /f "delims==" %%i in ('dir /a:d /b') do for /f "delims==" %%f in ('dir %%i /a:d /b') do (move "%%i\%%f\PM*.*" "%%i"&&rd "%%i\%%f" /s /q)
It moves the file and deletes the folder, just as I want. But the problem is that it only works when run from a FolderName folder, which defeats the time-saving purpose of the script. I don't know how to modify it to recurse into subfolders so I can run it from the top folder.
Thank you very much for any help!
#ECHO OFF
SETLOCAL
SET "sourcedir=u:\Carabidae"
FOR /f "tokens=1*delims=" %%a IN (
'dir /b /s /a-d "%sourcedir%\pm*.*" '
) DO IF EXIST "%%a" (
FOR %%p IN ("%%~dpa..\.") DO IF /i "%%~nxp"=="dor" (
ECHO %%a|FINDSTR /i "\\dor\\Stack" >NUL
IF NOT ERRORLEVEL 1 (
ECHO MOVE /y "%%~dpa\pm*.*" "%%~dpa..\"
ECHO RD /s /q "%%~dpa"
)
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
Find all of the pm*.* files, filenames to %%a
Ensure the parent directory is dor and ensure that \dor\stack\ is in the path. If so, move the file(s) and remove the directory.
The if exist gate ensure no hiccoughs if a target directory contains more than one pm*.* file.
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
The required RD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(RD to RD to actually delete the directories.
Add >nul at the end of the move command to suppress the move-report if required.
As usual, I'd suggest you test against a representative subtree first.
Here is a possible solution, given that only the XXX parts in your path sample are variable:
rem // Enumerate `FolderName*` directories:
for /D %%R in ("Carabidae\Pterostichinae\FolderName*") do (
rem // Enumerate `Stack*` sub-directories within `dor` sub-directories:
for /F "delims= eol=|" %%D in ('dir /B /A:D "%%~R\dor\Stack*"') do (
rem // Check for `PM*.*` files in `Stack*` sub-directories:
(
rem // Enumerate `PM*.*` files:
for /F "delims= eol=|" %%F in ('dir /B /A:-D "%%~R\dor\%%D\PM*.*"') do (
rem /* Move `PM*.*` file one directory level up, overwriting
rem an already existing file, if applicable: */
ECHO move /Y "%%~R\dor\%%D\%%F" "%%~R\dor\%%F"
)
) && (
rem /* Remove `Stack*` sub-directory after file movement;
rem this is skipped if no `PM*.*` files have been found in the `Stack*`
rem sub-directory, so when the `for /F %%F` loop did never iterate: */
ECHO rd /S /Q "%%~R\dor\%%D"
)
)
)
After having successfully tested whether or not the correct items are returned, remove the upper-case ECHO commands to actually move PM*.* files and remove Stack* directories!
I have a folder that contains subfolders with MP4 files. I'm trying to write a script that will move the MP4 files out of the subfolders into the root folder when ran. The batch file I wrote is working, but when the batch script runs again for new subfolders, the MP4 files that were already copied to the root folder, get moved up another level in the file structure. For example:
C:\MainRoot\Root\Subfolder\media.mp4
When script is ran, 'media.mp4' gets moved up to C:\Root\media.mp4 as desired.
But since I need the script to run on a scheduled task. The next time the script runs I get the following:
C:\MainRoot\media.mp4
Instead of just the MP4 file staying in C:\MainRoot\Root.
Here's my batch file so far to copy the mp4 files:
set root_folder=C:\MainRoot\Root
for /f "tokens=1* delims=" %%G in ('dir %root_folder% /b /o:-n /s ^| findstr /i ".mp4" ') do (
move /y "%%G" "%%~dpG..\%%~nxG"
)
What do I need to modify so that once moved, the MP4 files will stay in place?
Any help would be greatly appreciated!
Since all your source files seem to be at a certain directory level, a for /D loop could be wrapped around your for /F loop, which parses the output of a non-recursive dir command line (no /S):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=C:\MainRoot\Root"
set "_PATTERN=*.mp4"
rem // Loop through sub-directories:
for /D %%D in ("%_ROOT%\*") do (
rem // Loop through matching files:
for /F "eol=| delims=" %%F in ('dir /B "%%~fD\%_PATTERN%"') do (
rem // Avoid overwriting destination file:
if not exist "%_ROOT%\%%~nxF" (
rem // Move matching file one level up:
move /Y "%%~fD\%%~nxF" "%_ROOT%\%%~nxF"
)
)
)
endlocal
exit /B
If you are happy to overwrite as in your provided example then something as simple as this may suit your purpose:
#Echo Off
Set root_folder=C:\MainRoot\Root
If /I NOT "%CD%"=="%root_folder%" PushD "%root_folder%" 2>Nul||Exit/B
For /R %%G In (*.mp4) Do If /I NOT "%~dpG"=="%root_folder%\" Move "%%G">Nul 2>&1
If the files are only one folder deep you may prefer this:
#Echo Off
Set root_folder=C:\MainRoot\Root
If /I NOT "%CD%"=="%root_folder%" PushD "%root_folder%" 2>Nul||Exit/B
For /D %%G In (*) Do Move "%%G\*.mp4">Nul 2>&1
i've engaged with work in batch script.these things i need to do
1.i want to find the folder say like "name" in particular directory
ex:
c:\test\name
c:\test\b\name
c:\test\n\c\name
2.in the name folder, need to delete all sub folders and files and all which is more than 90 days.
i have changed my question now please give me an idea...
#ECHO OFF
SETLOCAL
SET "targetdir=U:\destdir"
ECHO(DEL "%targetdir%\*?*"
FOR /f "delims=" %%a IN (
'dir /b /ad "%targetdir%\*" '
) DO (
ECHO(RD /S /Q "%%~a"
)
GOTO :EOF
You would need to change the setting of targetdir to suit your circumstances. It could of course be replaced by a literal if you wish.
The required RD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(RD to RD to actually delete the directories.
The required DEL commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(DEL to DEL to actually delete the files.
the del and for commands could be cascaded with a & if required. The for is spread across a nuber of lines for clarity.
You're missing an asterisk * so that the folder set expands to all subdirectories of the _delete folder. Also, the /D /R construct seems unnecessary on second thought, because RD /S does already take care of deleting directories recursively.
FOR /D %%A IN ( folder_you_want_to_clean\* ) DO IF EXIST "%%A" RD /S /Q "%%A"
But it won't delete the files in the folder_you_want_to_clean folder itself, though. Do that with the DEL command - the /Q option suppresses the confirmation prompt, just like with the RD command:
DEL /Q folder_you_want_to_clean\*
Concrete example: Suppose the folder you want to clean is C:\data\oldstuff. Then just do:
FOR /D %%A IN ( C:\data\oldstuff\* ) DO IF EXIST "%%A" RD /S /Q "%%A"
All directories contained in C:\data\oldstuff will be gone (and of course, any files in those directories). But any files in C:\data\oldstuff itself will still be there! So to delete those as well, do:
DEL /Q C:\data\oldstuff\*
The code below moves all files under each movie folder into the appropriate movie folder, and if there are empty folders they'll be deleted.
Example:
Before:
D:\MOVIES
-----------\Bikini Spring Break
-------------------------------\EPCSKGCWZCXDJEH
------------------------------------------------------------\DVD
-----------------------------------------------------------------\P2HBSB5.iso
-----------------------------------------------------------------\0001.jpg
-----------------------------------------------------------------\lees.txt
After:
D:\MOVIES
------------\Bikini Spring Break
----------------------------------\P2HBSB5.iso
----------------------------------\0001.jpg
----------------------------------\lees.txt
#echo off
pushd "d:\MOVIES"
for /f "delims=" %%a in (' dir /ad /b ') do (
pushd "%%a"
for /r %%b in (*) do move /-y "%%b" .
for /f "delims=" %%c in (' dir /b /s /ad ^|sort /r') do rd "%%c" 2>nul
popd
)
popd
Is it possible to change something in the code from this batch command so only in selected folders the code is executed?
Maybe it's just a minor change if this batch command is placed into the "MOVIES" folder and executed from there.
Example:
If from these three movies only "Bikini Spring Break" and "Static" are selected in the "MOVIES" folder, I want only the code executed on these movies.
D:\MOVIES\Bikini Spring Break
---------------\Breaking the Girls
---------------\Static
This could work for you -
It uses drag and drop to process the folders that are selected.
Drag the folders onto the batch file.
What it doesn't do is check for filename clashes if any exist when moving the files recursively into a movie folder.
It is untested so make some copies of your folders and test it first.
#echo off
:loop
pushd "%~1"
for /r %%b in (*) do move "%%b" .
for /d %%c in (*) do rd /s /q "%%c"
popd
shift
if not "%~1"=="" goto :loop
I have a script to delete all subfolders and files in a folder:
FOR /D %%i IN ("D:\myfolder\*") DO RD /S /Q "%%i" & DEL /Q "D:\myfolder\*.*"
And it works great!
Only problem is that I would like to exclude one or more folders, like the XCOPY exclude feature.
I just cant figure how I could add that to the script.
You could try to hide the folders before the for-loop, and unhide them afterwards, like this:
ATTRIB +H D:\myfolder\keepit
FOR /D %%i IN ("D:\myfolder\*") DO RD /S /Q "%%i" DEL /Q "D:\myfolder\*.*"
ATTRIB -H D:\myfolder\keepit
there needs to be an & just between "%%i" and DEL or else it will delete folders but not files.
Here is a way that does not touch the excluded file and/or directory, so no attributes are altered:
rem // Change to target directory (skip if not found):
pushd "D:\Data" || exit /B 1
rem // Iterate through all subdirectories:
for /D %%D in ("*") do (
rem // Exclude a certain subdirectory:
if /I not "%%~nxD"=="ExcludeDir" rd /S /Q "%%~D"
)
rem // Iterate through all immediate files:
for %%F in ("*") do (
rem // Exclude a certain file:
if /I not "%%~nxD"=="ExcludeFile.txt" del "%%~F"
)
popd