I would like to recursively delete all files with a specific extension in a batch file.
I am aware of the following command:
del /s *.ext
However, this does on Windows also delete files with other extensions like e.g. .ext1 or .ext2 . The reason for this seems to be that the 8.3 file name of such a file ends with .ext and therefore also the files with longer extensions are matched.
I am looking for a replacement to the command above that recursively deletes all files with .ext extension but keeps files with longer extensions.
the where command works a bit differently (in regards to wildcards and short-names). Put a for /f loop around, and you're done. Your example would then translate to:
for /f "delims=" %%a in ('where /r . *.ext') do ECHO del "%%a"
Note: I disarmed the del command by just echoing it. Remove the ECHO after troubleshooting, when you are sure it does exactly what you want.
This also uses where.exe, but takes account of an issue not mentioned in another answer.
The issue is that where searches append each extension listed under %PATHEXT% to your .ext glob/spec. So whilst it will delete your target files, excluding files like .ext1 and .ext2 etc. it will now include for example, *.ext.com, *.ext.exe, *.ext.bat, *.ext.cmd, *.ext.vbs, *.ext.vbe, *.ext.js, *.ext.jse, *.ext.wsf, *.ext.wsh, and *.ext.msc etc.
The fix is to simply empty the content of %PATHEXT% before issuing the command. The following method does so within the For loop parenthsized command. As that is ran in another cmd.exe instance, it will not affect the instance in which the rest of your script resides:
#For /F "Delims=" %%G In ('"(Set PATHEXT=) & "%__APPDIR__%where.exe" /F /R "C:\SourceDir" "*.ext" 2>NUL"') Do #Del /A /F %%G
Obviously, you would modify, C:\SourceDir to contain the root location you require. The other current answers, use the current directory. If you want that, change it to ., or if you want the directory base as that of your batch file, change it to %~dp0.. Please do not remove any doublequotes.
Here are some alternative method examples, (please remember to adjust the drive/path/extension as needed)
If you wish to stick with the more traditional Dir command, then you could pipe the results through the findstr.exe utility, to exclude those matching the 8.3 names:
#For /F "Delims=" %%G In ('"Dir /B /S /A:-D "C:\SourceDir\*.ext" 2> NUL | "%__APPDIR__%findstr.exe" /I /L /E ".ext""') Do #Del /A /F "%%G"
You could also use the forfiles.exe utility for the task:
#"%__APPDIR__%forfiles.exe" /P "C:\SourceDir" /S /M "*.ext" /C "\"%__APPDIR__%cmd.exe\" /C \"If #IsDir==FALSE Del /A /F #File\""
Or this excruciatingly slow WMIC.exe utility method:
#"%__APPDIR__%wbem\WMIC.exe" DataFile Where "Drive='C:' And Path Like '\\SourceDir\\%%' And Extension='ext'" Delete 1> NUL 2>&1
Stephans answer is the shorter version, but you can use findstr's regex as well to match that the end of the name should be .ext
for /f "delims=" %%i in ('dir /b /s ^| findstr /IRC:"\.ext$"') do echo del "%%~i"
Related
I'm starting to learn how to use the CMD in Windows. And I have a directory full of documents with names like "Document_1.txt", "Document_5.txt" etc... (All with Document_#.txt but there's no pattern in the numbers).
I want to move each file to a folder named "Text_#" and change the name of the file to "text_#.txt". How can I do that?
My attempt is this (simple) batch file (actually I think I don't even need to create a batch file, but was easy to do this way.)
#ECHO OFF
FOR /L %%i IN (1,1,24) DO (
FORFILES /M *.txt /C "cmd /c IF #fname==Document_%%i (MD Text_%%i) & (MOVE #file Text_%%i\text_%%i.txt)"
The problem is that the IF command never returns true, although when writing ECHO #fname it prints "Document_#", so I suppose that even if what I see is the same there is some difference that I cant see using the ECHO command.
Anybody could give me some solution to this problem?
In my opinion the simplest way is to forget about using the ForFiles command for this, and use a For /F loop instead. To ensure that only the files with a .txt extension whose basename ends with _# or _##, (where # represents an integer), use the Dir command and filter its results with the help of FindStr. Then you can use MD to make the directories if it don't already exist and move the files into it, renaming them with their new name.
From the cmd with the current directory as that holding your files:
For /F "Tokens=1,* Delims=_" %G In ('Dir /B /A -D Document_??.txt ^| %__AppDir__%findStr.exe /I "_[0123456789]*\.txt$"') Do #If Not Exist Text_%~nH (MD Text_%~nH) & Move /Y %G_%H Text_%~nH\text_%H 1>NUL
If you want to do that from a batch-file instead, also within the same current directory:
#For /F "Tokens=1,* Delims=_" %%G In (
'Dir /B /A -D Document_??.txt ^| %__AppDir__%findStr.exe /I "_[0123456789]*\.txt$"'
) Do #(
If Not Exist Text_%%~nH MD Text_%%~nH
Move /Y %%G_%%H Text_%%~nH\text_%%H 1>NUL
)
The above answers assume either one or two digits at the end of the file basenames, (as you were limiting yours to numbers from 1 to 24 inclusive) I have also left out quoting because your provided names didn't warrant it. If those were not truly representative, you'll need to introduce those as necessary and make any other changes which were outside of the question posed.
I need to count the number of .txt files in a Windows 10 directory.
I am starting with the following code as a batch-file:
#ECHO OFF
for %%f in (*.*) do echo %%f
Does anyone know how I can do it?
The method will most likely depend upon the rest of the script; but for the question only.
Probably the simplest method would be to use where.exe and find.exe together:
Where .:*.txt 2>Nul|Find /C /V ""
Should you wish to save the count as the value content of a variable, you can use a For /F loop incorporating either where.exe or the Dir command. Please note however that in both a standard For loop, (For %%A In (*.txt)), and when using the Dir command, (Dir *.txt), file extensions beginning with .txt are returned as opposed to those ending with .txt, returned by where.exe. In order to account for this, in my Dir version, I have piped the results through a findstr.exe to ensure that only .txt files are counted:
Where method:
#Echo Off
Set "#=0"
For /F %%A In ('"Where .:*.txt 2>Nul|Find /C /V """')Do Set "#=%%A"
Echo(%#%
Pause
Dir method:
#Echo Off
Set "#=0"
For /F %%A In ('"Dir/B/A-D-L *.txt 2>Nul|FindStr/I "txt$"|Find /C /V """'
)Do Set "#=%%A"
Echo(%#%
Pause
I have downloaded a series of torrent files, and want to delete some of the attached files that came within them. I'm familiar with forfiles but don't know how to set up a searchmask from a file of unwanted extensions (i.e. *.jpg, *.txt, etc.).
So far, I have captured 17 extensions that I won't ever need, and would hate to have to loop the entire batch program for an eighteenth time if I find another.
First, prepare a list of all the unwanted files with dir /b /s, capturing the output into a temporary text file;
dir /b /s *.txt /s *.jpg /s *.etc >%temp%\unwanted.lst
see help dir for an explanation on the /b and /s switches.
Then, delete the files in the list with a simple for /f over the contents of the captured list
for /f "delims=" %%a in (%temp%\unwanted.lst) do del %%a
See help for to understand what the /f does.
So, putting all the pieces together, your batch file would be something similar to this one:
#echo off
set "otf=%temp%\unwanted-%random%.lst"
dir /b /s *.jpg /s *.txt /s *.etc >%otf%
for /f %%a in (%otf%) do echo del "%%a"
echo del %otf%
note that it uses the %random% pseudovariable to minimize the risk of collisions
test in your situation and remove the echo commands
I'm trying to write a .bat file to delete all files from a directory that look like "r" concatenated with a number of indeterminate length with a .sas7bdat ending.
e.g.: r2343.sas7bdat, r2309483.sas7bdat, etc.
The problem is, that I also have a file called "ranker_interface.sas7bdat", so I can't just do:
del "C:\temp\r*.sas7bdat"
I've tried Googling this up and down, but I haven't been able to figure it out. Is there any way of excluding a particular value from a wildcard?
for /L %%a in (0,1,9) do ECHO del r%%a*.sas7bdat
would possibly be easiest.
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.
If you are running this directly from the prompt rather than as a line in a batch file, change all %%a to %a.
This is the old school MSDOS way of getting around this:
attrib +h "C:\temp\ranker*.sas7bdat"
del "C:\temp\r*.sas7bdat"
attrib -h "C:\temp\ranker*.sas7bdat"
The attrib command hides the files you don't want deleted from the DEL command,
and then unhides them again.
To list down all files from folder that are like 'r*.sas7bdat', exclude the one from the list called ranker_interface.sas7bdat and delete the rest you can use this command from within batch file:
for /f "tokens=*" %%a in ('dir /b r*.sas7bdat ^| find /v "ranker_interface.sas7bdat"') do del /f /q %%a
It is written the way to be executed from the folder directly.
This will delete all 'r*.sas7bdat' but the one specified by find /v - exclusion, that can eventually be followed by another find /v exclusion, so something like:
for /f "tokens=*" %%a in ('dir /b r*.sas7bdat ^| find /v "ranker_interface.sas7bdat" ^| find /v "rxxxxx.sas7bdat"') do del /f /q %%a
Not the best way if you want to exclude more than one file. If you want to exclude more than one file, then you can put your excluded filenames into singel file and isntead of directly running del command further for followed by if statements can be done and compare the file if can be found in exclusion list file, that contain file name on each row. Batch can look like this then:
#echo off
for /f "tokens=*" %%a in ('dir /b r*.sas7bdat') do (
for /f "tokens=*" %%x in ('type exclusion.txt ^| find /c "%%a"') do (
if "%%x" EQU "0" (del /f /q %%a)
)
)
This will delete all files in your directory that are like 'r*.sas7bdat', except those listed down in file 'exclusion.txt'
Hope this helps
I need to replace every icon (AutoCAD 2010.LNK) found on the computer with another .LNK using batch.
The icon\ shortcut as we well know can be found anywhere and as many times as the user likes.
How can I achieve this?
first, read HELP FOR
and then try this in a command line
FOR /F "tokens=*" %a in ('dir /B /S "AUTOCAD 2010.LNK"') do ECHO COPY new.lnk %a
experiment with from various locations and test carefully
then create a bat file with the following contents. Note the change of %a into %%a and the removal of the 'echo'
#echo off
PUSHD C:\
FOR /F "tokens=*" %%a in ('dir /B /S "AUTOCAD 2010.LNK"') do COPY new.lnk %%a
POPD
#ECHO OFF
SET "linklist=%USERPROFILE%\linklist.txt"
SET "replacement=D:\path\to\replacement.lnk"
ECHO Searching...
DIR /B /S "C:\AutoCAD 2010.LNK" >%linklist%
DIR /B /S "D:\AutoCAD 2010.LNK" >>%linklist%
:: add similar rows for every drive letter you want to be included
ECHO Replacing...
FOR /F "tokens=*" %%f IN (%linklist%) DO COPY %replacement% %%f
ECHO Finished.
A couple of notes:
Your replacement shortcut file must be named differently (like AutoCAD 2010.LNK.new, for example).
In Windows Vista/7 you will probably be prohibited from overwriting files in certain folders unless you are running the script with elevated rights.