I've been trying to figure this out for some time now, and I have been searching the web immensely, but I couldn't find the right answer just yet.
So here's my problem:
I want to create a batch file, that searches through all subfolders of a certain directory, finds a specific file and then deletes everything but that file in the folder that the searched file was in.
What I came up with so far is this:
cmd /k for /f %%a IN ('dir /b /s Neuer') do if not [%%a] == [index.txt] del /q %%a
But that deletes just every file in every subfolder - not quite what I want.
Can anyone help?
#echo off
setlocal
if "%~2" == "" (
echo/Usage: %~nx0 ^<directory^> ^<file^>
echo/
echo/%~nx0 will search the given ^<directory^> and its subdirectories
echo/looking for ^<file^>. If the ^<file^> is found, then all the other
echo/files and subdirectories in the same directory as ^<file^> will be
echo/deleted. If more than one ^<file^> is found then this action is
echo/repeated for all matches. Wildcards are not accepted; ^<file^> can
echo/be the name of either a file or a directory.
exit /b
)
if not exist "%~1\" (
echo/%nx0: "%~1" does not exist or is not a directory
exit /b
)
set "TARGETNAME=%~2"
for /r "%~1" %%t in (*) do call :checkFile "%%~t"
for /r "%~1" %%t in (.) do call :checkDir "%%~t"
exit /b
:checkFile
if not "%~nx1" == "%TARGETNAME%" exit /b
echo/* Found "%~1"
echo/ - Deleting files in directory "%~dp1" . . .
for %%f in ("%~dp1*") do call :delFile "%%f"
echo/ - Deleting directories in directory "%~dp1" . . .
for /d %%d in ("%~dp1*") do call :delDir "%%d"
exit /b
:checkDir
set "TESTNAME=%~1"
call :checkFile "%TESTNAME:~0,-2%"
exit /b
:delFile
if "%~nx1" == "%TARGETNAME%" exit /b
echo/ : del "%~1"
rem del "%~1"
exit /b
:delDir
if "%~nx1" == "%TARGETNAME%" exit /b
echo/ : rd /q /s "%~1"
rem rd /q /s "%~1"
exit /b
Notes:
In production one would of course do some error checking.
Maybe some files cannot be deleted because they have the readonly attribute, or the user running the script does not have the appropriate privileges, or they are in use, etc.
Maybe some directories cannot be deleted, for similar reasons, or because they contain hidden files, or because they contain files which cannot be deleted.
The script looks for both files and directories with the given name; it is easy to see how to limit the search to files only.
The script will do its work for all files or directories matching the given name.
As illustrated here the script does not actually delete anything, it just prints what would be deleted. To make it actually do the deletion just remove the rem in front of del and rd.
Exactly for this kind of issues, the command forfiles has been invented:
ForFiles explanation
Related
I'm trying to copy some non specific folders with their content, but can't find a way to do it. My problem is every time I try to use any of the copy commands it tells me it's an "Invalid number of parameters", or "0 File(s) copied", or "File not found -", or it copies everything from Folder1, (not just the non specific folders).
What I mean by "non specific" is a folder which has an unknown name, i.e. *.
This is what I have tried:
xcopy /y "C:\Folder1\Something_*" "C:\Folder2"
copy /y "C:\Folder1\Something_*" "C:\Folder2"
robocopy "C:\Folder1\Something_*" "C:\Folder2"
/+ adding " * " in front of "Something_*"
I have also tried a lot more smaller things, that I don't see a need to add.
I'm a little lost on what to do at this point, and feel like I have been looking everywhere for a solution with no luck.
Edit: i found a way to do this and it's so much better, this is how
for /R "%sourcedir%" %%A in (Something_*) do copy /y "C:\Folder1\%%~A" "C:\Folder2"
#ECHO OFF
SETLOCAL
rem The following settings for the source directory, destination directory, target directory,
rem batch directory, filenames, output filename and temporary filename [if shown] are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files\t w o"
SET "destdir=u:\your results"
:: Version 1 - all files arrive in the destination directory
FOR /f "delims=" %%b IN ('dir /b /ad "%sourcedir%\Something_*" ') DO (
COPY /b /y "%sourcedir%\%%b\*" "%destdir%\" >NUL 2>nul
FOR /f "delims=" %%c IN ('dir /b /s /ad "%sourcedir%\%%b" ') DO (
COPY /b /y "%%c\*" "%destdir%\" >NUL 2>nul
)
)
cls
dir/s "%destdir%"
PAUSE
:: This is a routine I use for testing. It simply deletes the directory named and restores it, empty
CALL deltreey /r "%destdir%">NUL
:: Version 2 - preserve tree structure
FOR /f "delims=" %%b IN ('dir /b /ad "%sourcedir%\Something_*" ') DO XCOPY /y /s /e "%sourcedir%\%%b" "%destdir%\" >NUL 2>nul
)
cls
dir/s "%destdir%"
PAUSE
:: This is a routine I use for testing. It simply deletes the directory named and restores it, empty
CALL deltreey /r "%destdir%">NUL
GOTO :EOF
I have a batch file, that constantly checks to see if there are any files in a directory:
#echo off
cls
mode 15,5
cd C:\Users\Toni\Downloads\
goto mark
:mark
set var=2
dir /b /a "Downloads\*" | >nul findstr "^" && (goto exin) || (goto mark1)
goto mark
:mark1
cls
#ping -n 10 localhost> nul
goto mark
:exin
start /B C:\Users\Toni\Downloads\Test\download.bat
exit
if ther are any files in this folder, it moves them.
#echo off
cls
cd C:\Users\Toni\Downloads\Downloads
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.rar C:\Users\Toni\Downloads\Archive
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.zip C:\Users\Toni\Downloads\Archive
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.exe C:\Users\Toni\Downloads\Setups_usw
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.msi C:\Users\Toni\Downloads\Setups_usw
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.mp3 E:\-_MUSIC_-\Musik
xcopy /Y C:\Users\Toni\Downloads\Downloads\*.wav E:\-_MUSIC_-\Musik
xcopy /S /E /Y /EXCLUDE:C:\Users\Toni\Downloads\Test\excludedfileslist.txt C:\Users\Toni\Downloads\Downloads\*.* C:\Users\Toni\Downloads\Sonstiges
goto err
:err
if errorlevel 1 ( dir /arashd >> "C:\Users\Toni\Downloads\Test\somefile.txt" 2>&1 ) else ( del /[!*.part] * )
goto end
:end
start /B C:\Users\Toni\Downloads\Test\run.cmd
exit
However, I do not want to move files that are in the process of downloading (ie. I don't want to move partial files with a .part extension).
I tried using an argument to the del command like so:
del /[!*.part] *
but it doesn't seem to work.
How can I avoid moving partial files with the .part extension?
I would probably look at the file extension (using "substitution of FOR variables").
SET "TARGET_DIR=C:\Users\Toni\Downloads\Downloads"
FOR /F "delims=" %%f IN ('dir /b "%TARGET_DIR%"') DO (
REM Ensure it doesn't have '.part' as an extension.
IF NOT "%%~xf"==".part" (
REM Ensure there's not a corresponding ".part" file.
IF NOT EXIST "%TARGET_DIR%\%%~f.part" (
DEL "%TARGET_DIR%\%%~f"
)
)
)
This will delete any file in TARGET_DIR that doesn't have ".part" as a filename extension or have a corresponding ".part" file. (In my experience downloaders that do the ".part" thing also reserve the name of the "finished" file as well, which you'd probably not want to delete.)
Another possible solution (shorter than #mojo's one):
#echo off
cd /d C:\Users\Toni\Downloads\Downloads
attrib +h *.part
for /f "delims=" %%A IN ('dir /b /A:-H') do del %%A
attrib -h *.part
This, will hide all .part files, delete all other files and remove again the hidden attribute.
Hi have written a batch file to delete files and folders of a specified location
all is fine but the issue is that when there is no such F: drive in the machine then
the batch file delete the content of the folder where it has been kept .
Can any one help to modify the batch file and to write a condition to check wether that drive is present or not
My batch file
set folder="F:\PortalViewState"
cd /d %folder%
for /F "delims=" %%i in ('dir /b') do (rmdir "%%i" /s/q || del "%%i" /s/q)
pushd "F:\PortalViewState" 2>nul &&( rmdir . /s /q & popd )||(echo Folder not present)
Change drive and active directory to the target folder, if no failure, then remove anything inside it (the folder can not be deleted as it is the active directory) and return to the previous active directory
#ECHO Off
SETLOCAL
pushd
set folder="F:\PortalViewState"
cd /d %folder% 2>nul
ECHO ERRORLEVEL=%errorlevel%
IF "%cd%"==%folder% (ECHO Switched to %folder%) ELSE (ECHO failed to switch to %folder%)
set folder="U:\sourcedir"
cd /d %folder% 2>nul
ECHO ERRORLEVEL=%errorlevel%
IF "%cd%"==%folder% (ECHO Switched to %folder%) ELSE (ECHO failed to switch to %folder%)
POPD
GOTO :EOF
This shows you two ways.
The surrounding pushd/popd simply saves and restores my test directory.
The u:\sourcedir directory exists on my system, so I get errorlevel=0 and a switched message. F: does not exist, so I get an errorlevel=1 and failed message.
The 2>nul suppresses the error message when the destination drive does not exist.
you don't need to pushd %folder%
read help rd and then, simply
rd /s /q "f:\portalviewstate"
Or, check that it exists or not and act accordingly
if not exist %folder% goto :somepart
I am looking to create a batch file that when given a pathway, it will count all the folders and sub folders within it. So far I am only able to gather the number of folders within the 1st level of the pathway. I will then pipe it to a text file.
Here's what I have so far:
for /f %%a in ('dir /b /ad %folder%^|find /c /v "" ') do set count=%%a
echo %count% folder(s^)>> !output!
Am I close to getting what I want? What do I need to tweek?
Thanks!
Add /s to include all subfolders:
for /f %%a in ('dir /b /s /ad %folder%^|find /c /v "" ') do set count=%%a
echo %count% folder(s^)>> !output!
A small edit of this answer: Batch file to list files and folders in a simple format
#echo off
setlocal disableDelayedExpansion
pushd %1
set "tab= "
set "indent="
call :listFolder >report.txt
exit /b
:listFolder
setlocal
set "indent=%indent%%tab%"
for /d %%F in (*) do (
echo %indent%.\%%F
pushd "%%F"
call :listFolder
popd
)
exit /b
Here's how I solved the problem.
if exist "File Count" del "File Count"
dir "%~d1%~p1\*.*" /b /s >> "File Count"
find /c "." "File Count"
First we check to see if a file exists, and if so, delete it. Then we get a list of files and dump that to our file. then run FIND on the file. FIND will handily give us a big label, so the name of the file might as well be something attractive and human readable.
I am personally interested in a specific filetype, so I changed . into *.jpg but the principle is the same.
We have a batch script that removes files (del) and directories (rd). Does anyone know how to halt (fail) execution of the script if any of these delete statements fail? They could fail if a file/directory is locked by Windows. Thanks.
Update
Statements I'm using:
Del: del *.* /S /Q
RD: FOR /D %%G in (*) DO RD /s /q %%G
For deleting the files, you can first try to ren (rename) the file.
ren will set ERRORLEVEL to 1 if the file is locked. Add quotes around filename.
#echo OFF
:: Delete all files, but exit if a file is locked.
for %%F in (*.*) do (
#echo Deleting %%F
ren "%%F" tmp 2> nul
if ERRORLEVEL 1 (
#echo Cannot delete %%F, it is locked.
exit /b 1
)
del tmp
)
I suspect you may be able to do the same thing for directories, but I can't seem to figure out how to get a directory locked so I can test. The following may work:
:: Remove all directories, but exit if one is locked.
FOR /D %%G in (*) DO (
#echo Removing %%G
ren "%%G" tmpdir 2> nul
if ERRORLEVEL 1 (
#echo Cannot remove %%G, it is locked
exit /b 1
)
RD /s /q tmpdir
)
DEL doesn't return an errorlevel if the file is locked. I just did a test with excel file and I saw a zero (on Windows XP).
It might be better to use IF EXIST for the file to be deleted after you do the delete.
del file.txt
if exist file.txt ECHO "FAIL"
AFTER EDIT
Disclaimer: I have no idea how this performs...
You could do this for the files
DIR /B /S /A-d > c:\filestodelete.txt
del *.* /S /Q
FOR /F %%i in (c:\filestodelete.txt) DO (
IF EXIST %%i ECHO %%i STILL EXISTS
)
then for the directories
DIR /B /S /Ad > c:\directoriestodelete.txt
FOR /D %%G in (*) DO RD /s /q %%G
FOR /F %%i in (c:\directoriestodelete.txt) DO (
IF EXIST %%i ECHO %%i STILL EXISTS
)
EDIT: Right, so del does not set the ERRORLEVEL correctly. See ERRORLEVEL on DEL and Windows delete command can fail silently
PREVIOUS (incorrect) SOLUTION
You should check the errorlevel.
For example:
del file.txt
if errorlevel 1 goto FAIL
:PASS
echo Worked!
goto :END
:FAIL
echo Failed!
exit /B 1
:END
Here's my preferred way to check for errors while deleting files. We redirect the "error output" (standard file "2") to a file (e.g. delCmd.err). Then we use the FOR command as a way to get access to the ~z "file size" operater. If the size of the output file is not 0, then we know that "del" got an error... we display the error with the "type" command and exit the batch file with a non-zero error code:
del unwanted.txt 2> delCmd.err
FOR /F "usebackq" %%A IN ('delCmd.err') DO set size=%%~zA
if not "%size%"=="0" (
echo Error deleting unwanted.txt
type delCmd.err
exit /B 1
)
Here is a shorter version of the result monitoring variant. This is using 2>&1 trick to redirect stderr to stdout and for /f to check for any output.
#echo off
setlocal
set error=0
for /f %%i in ('del notepad2.exe 2^>^&1') do set error=1
echo %error%
Just for your information. The DEL command does return an error code if a serious error occurs, however it's behavior is way beyond our intuition that people would simply believe that the error code doesn't work at all.
This is what I've tested in DEL command in Windows 7:
Successful deletion of all files: 0 (of course)
Some files deleted, some files missing: 0 (intuition expects 1)
Deletion failure due to no permission or a read-only medium: 0 (intuition expects ≥ 1)
Non-existent drive or drive not ready (such as no CD on a CD-ROM drive): 1 (yes, you get it, but I will expect a higher error code)
Invalid path: 1 (I will expect a higher error code, too)
And, if you specify a list of files to DEL command, where at least one of the files fit the last two kinds of error mentioned above, then none of the files in the list will be deleted at all.
There is a script that will work like a charm.
It tests deletion failure by testing the existence of the supposedly deleted file/directory.
The output will be an existing c:\mydirectory with completely empty content.
Any error breaks the process and is reported.
The only downside is that directories are removed recursively, because there is no simple way to start deleting directories starting with the most "sub" directories.
#echo OFF
set path_to_clean=c:\mydirectory
#echo -Deleting Files
dir /A-D /S /B %path_to_clean%\* > fileslist.txt
for /F %%F in (fileslist.txt) do (
#echo Deleting %%F
del %%F 2> nul
if exist %%F (
#echo Cannot delete %%F, it is locked.
goto errorhandling
)
)
del fileslist.txt
#echo -Deleting Files done
#echo -Deleting Directories
dir /AD /B %path_to_clean%\* > directorieslist.txt
for /F %%D in (directorieslist.txt) do (
#echo Deleting %path_to_clean%\%%D
rmdir /S /Q %path_to_clean%\%%D 2> nul
if exist %path_to_clean%\%%D (
#echo Cannot delete %path_to_clean%\%%D. This folder or one of its sub-directories is locked.
goto errorhandling
)
)
del directorieslist.txt
#echo -Deleting Directories done
:errorhandling
rem some code here
These seem to work for me:
RD:
FOR /D %d IN (*) DO ( RD /S /Q "%d" & IF EXIST "%d" EXIT /B 1 )
DEL:
FOR %f IN (*.*) DO ( DEL /Q "%f" & IF EXIST "%f" EXIT /B 1 )
No idea about the performance though.
You can add flag /F to DEL for a "force delete" mode.
For rd and rmdir you can do
rd "some directory" || rem
this will set the errorlevel correctly - see
Hi This should work as well
#echo off
for /f %%i in ('del notepad2.exe 2^>^&1') do set ERRORLEVEL=1
IF %ERRORLEVEL%=1 then exit