Delete files with specific extension except a particular file - windows

I have a folder which contains the following files:
How can I delete all files with extension .rst (File1.rst, File2.rst, File3.rst, File4.rst, File5.rst) except the file "index.rst" from a batch file.
I have tried this, but it's not working:
for /f "skip=1 delims=" %%i in ('D:\hfTools\Projects\Validation-Source\Docs\source /b "*.rst"') do #(if "%i" neq "index.rst" echo %i)
Any help would be welcome. Thank you.

Here's an example of how to perform the task using the ForFiles command, forfiles.exe:
#%__AppDir__%forfiles.exe /P "D:\hfTools\Projects\Validation-Source\Docs\source" /M "*.rst" /C "%__AppDir__%cmd.exe /D /C If #IsDir==FALSE If /I Not #FName==0x22index0x22 Del /A /F #File"
Here's an example of how to perform the task using the Dir command:
#Echo Off
SetLocal EnableExtensions
If Exist "D:\hfTools\Projects\Validation-Source\Docs\source\*.rst" (
PushD "D:\hfTools\Projects\Validation-Source\Docs\source" && (
For /F "EOL=? Delims=" %%G In ('Dir /B /A:-D "*.rst" ^
^| %__AppDir__%findstr.exe /E /I /L ".rst" ^
^| %__AppDir__%findstr.exe /I /L /V /X "index.rst"'
) Do Del /A /F "%%G"
PopD
)
)
My preference however would be to use the Where command, where.exe:
Example batch-file
#Echo Off
SetLocal EnableExtensions
For /F "EOL=? Delims=" %%G In ('%__AppDir__%where.exe ^
"D:\hfTools\Projects\Validation-Source\Docs\source":"*.rst" ^
^| %__AppDir__%findstr.exe /E /I /L /V "\index.rst"'
) Do Del /A /F "%%G"
You could even do that as a single line batch-file:
#For /F "EOL=?Delims=" %%G In ('%__AppDir__%where.exe "D:\hfTools\Projects\Validation-Source\Docs\source":"*.rst"^|%__AppDir__%findstr.exe /EILV "\index.rst"')Do #Del /A/F "%%G"
Or directly from a cmd window:
For /F "EOL=?Delims=" %G In ('%__AppDir__%where.exe "D:\hfTools\Projects\Validation-Source\Docs\source":"*.rst"^|%__AppDir__%findstr.exe /EILV "\index.rst"')Do #Del /A/F "%G"
And for an off topic bonus, because for general use it seems easier; use powershell instead:
Remove-Item -Path "D:\hfTools\Projects\Validation-Source\Docs\source\*.rst" -Exclude "index.rst" -Force
You could even run that using a one line batch file, if you really needed to:
#%__AppDir__%WindowsPowerShell\v1.0\powershell.exe -NoP "RI 'D:\hfTools\Projects\Validation-Source\Docs\source\*.rst' -E 'index.rst' -Fo"

Not tested:
forfiles /M *.rst /C "cmd /c if #file!=index.rst del #file"
Explanation:
/M *.rst # only consider *.rst
if ... # #file is the filename as found by forfiles
# != is this the correct way say "does not equal"?

You are actually quite close, you just forgot to double a few %-signs and you missed the dir command:
rem // Change to target directory, because `dir /B` only returns pure file names:
pushd "D:\hfTools\Projects\Validation-Source\Docs\source" && (
rem // Capture the output of `dir /B` and loop through the lines/files:
for /f "delims= eol=|" %%i in ('
dir /B /A:-D-H-S "*.rst"
') do #(
rem // Check file name against predefined exception:
if /I not "%%i"=="index.rst" (
rem // Actually delete the currently iterated file:
ECHO del "%%i"
)
)
popd
)
Once you are satisfied with the output, remove the upper-case ECHO command to actually delete files.
Note that the pattern *.rst in the dir /B command line is actually checked against both long and short file names (if the latter is enabled), so it actually matches files whose extensions begin with rst (if applicable).
If the files to delete always match the pattern File*.rst you do not even need the if condition:
rem // Change to target directory, because `dir /B` only returns pure file names:
pushd "D:\hfTools\Projects\Validation-Source\Docs\source" && (
rem // Capture the output of `dir /B` and loop through the lines/files:
for /f "delims= eol=|" %%i in ('
dir /B /A:-D-H-S "File*.rst"
') do #(
rem // Actually delete the currently iterated file:
ECHO del "%%i"
)
popd
)

This is easily done using PowerShell. If you are on a supported version of Windows, PowerShell will be available. When you are confident that the correct files will be removed, remove the -WhatIf from the command.
Remove-Item -Path './*' -Include '*.rst' -Exclude 'index.rst' -WhatIf
Id you must do it from a cmd.exe (.bat file) script:
powershell -NoLogo -NoProfile -Command ^
"Remove-Item -Path './*' -Include '*.rst' -Exclude 'index.rst' -WhatIf"

Related

batch file - use dir /s /b %~dp0 to get list of files and remove %~dp0's path from output

ECHO ===FILES TO TRANSFER===
FOR /f "usebackq tokens=*" %%G IN (`DIR /B /S "%~dp0Files"`) DO #ECHO %%G
The output is the full path of the file/dir but I want to make it simpler by removing %~dp0's path from the output
This is the methodology I'd suggest you incorporate, which protects filenames which may include ! characters and limits the output to files, as per your stated requirement:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
For /F Delims^=^ EOL^= %%G In ('Dir /B/S/A-D "%~dp0Files" 2^>NUL')Do (
Set "_=%%G" & SetLocal EnableDelayedExpansion
Echo(!_:*%~dp0Files=.! & EndLocal)
Pause
If you'd prefer not to have a relative path type output then change !_:*%~dp0Files=.! to !_:*%~dp0Files\=!
Alternatively, you could grab the relative paths using the slower, forfiles.exe utility:
%__AppDir__%forfiles.exe /P "%~dp0Files" /S /C "%__AppDir__%cmd.exe /D/Q/C If #IsDir==FALSE Echo #RelPath"
If you prefer it without doublequotes then this modification should do that:
%__AppDir__%forfiles.exe /P "%~dp0Files" /S /C "%__AppDir__%cmd.exe /D/Q/C If #IsDir==FALSE For %%G In (#RelPath)Do Echo %%~G"
And if you wanted it without the leading .\ then perhaps:
%__AppDir__%forfiles.exe /P "%~dp0Files" /S /C "%__AppDir__%cmd.exe /D/Q/C If #IsDir==FALSE For /F 0x22Tokens=1*Delims=\0x22 %%G In (#RelPath)Do Echo %%H"
You could also do this by leveraging powershell.exe:
%__AppDir__%WindowsPowerShell\v1.0\powershell.exe -NoProfile Get-ChildItem -Path "%~dp0Files" -File -Force -Name -Recurse
which could possibly be done, (not recommended), in as short a line as:
powershell -NoP ls "%~dp0Files" -File -Fo -Na -Rec
just remove %~dp0 from each entry (Note: that doesn't work with %%G metavariables, you have to use a "normal" environment variable):
#echo off
setlocal enabledelayedexpansion
ECHO ===FILES TO TRANSFER===
FOR /f "usebackq tokens=*" %%G IN (`DIR /B /S "%~dp0"`) DO (
set "file=%%G"
echo !file:%~dp0=!
)
To retrieve the relative path to a given root without string manipulation, you could use the xcopy command with its /L option, which lists relative paths to files it would copy without /L:
pushd "%~dp0" && (
for /F "delims= eol=|" %%G in ('xcopy /L /S /Y /I "Files" "%TEMP%" ^| find "\"') do (
echo(%%G
)
popd
)
pushd and popd are used to change into and return from the root directory, respectively.
The find command is used to suppress xcopy's summary line # File(s).

Delete all files in a folder but skip files that cointain certain string

I'm trying to clean the temp files, but I want skip some files that cointain a certain name. No matter the extension it is.
Tried this way:
#echo off
setlocal EnableDelayedExpansion
for /f "eol=: delims=" %F in ('dir "%windir%/temp" /b /a-d * ') do find "TESTE" %F > nul || del "%F"
pause
Wanted all files that cointains TESTE in name got skipped from deletation.
But my script not even run.
Can someone explain me what is wrong?
It is not absolutely clear whether you want to exclude files from deletion whose names or whose contents include a certain string; anyway, this is for the former:
pushd "%WinDir%\TEMP" && (
for /F "delims= eol=|" %%F in ('
dir /B /A:-D "*.*" ^| findstr /V /I /C:"TESTE"
') do (
ECHO del /F "%%F"
)
popd
)
Once you are satisfied with the output, remove the upper-case ECHO command.
The above script would also not delete files whose extensions contain the given string. But if you want to regard only the base name, you might want to use this code instead:
pushd "%WinDir%\TEMP" && (
for /F "delims= eol=|" %%F in ('
dir /B /A:-D "*.*"
') do (
set "NAME=%%~nF"
setlocal EnableDelayedExpansion
if /I "!NAME:TESTE=!"=="!NAME!" (
endlocal
ECHO del /F "%%F"
) else endlocal
)
popd
)
You should be able to use findstr.exe with its /V and /M options to list your unwanted files.
#SetLocal EnableExtensions
#For /F "Delims=" %%G In (
'%__AppDir__%findstr.exe /VPMLI "TESTE" "%SystemRoot%\TEMP\*" 2^>NUL'
)Do #Del /A/F "%%G"
#Pause
Please note that the \Windows\Temp directory is usually protected, so you may need to run this script 'as administrator'.

Write a script to recursively list directories and files within it in Batch script

I am trying to write a batch script that recursively lists all directories and their files with *.js type in the below format:
For example, if I start with the C:\project directory
c:\project
project.js
project_time.js
c:\project\core
core.js
core_render.js
core_application.js
I tried to implement the above logic in code as follows:
#echo off
for /r %%f in (*.js) do (
echo %%f >> names.txt
)
pause
I was not able to print the directory under which the files are listed.
#echo off
setlocal disabledelayedexpansion
set "lastdir="
( for /r %%A in (*.js) do (
set "nextdir=%%~dpA"
setlocal enabledelayedexpansion
if /i not "!lastdir!" == "!nextdir!" (
rem Empty line and directory path.
if defined lastdir #echo(
#echo !nextdir!
)
endlocal
rem Filename.
#echo %%~nxA
set "lastdir=%%~dpA"
)
) > "names.txt"
The lastdir variable is to record the last directory path so it is echoed only once.
If lastdir is different to %%~dpA:
If lastdir is defined, then an empty line will be echoed.
Directory path of found file is echoed.
Filename is always echoed.
for modifiers dp is the drive and path. nx is the name and extension.
setlocal enabledelayedexpansion is used only where needed so paths with ! are not vulnerable.
I am not going to suggest a command line solution as it would be very long. Instead suggest use of tree command if the output format is suitable.
Here's an untested example, (I'm not expecting it to be quick if your base directory is large):
#Echo Off
(
For /F "Delims=" %%G In ('Dir /B /S /A:D "C:\Project" 2^> NUL') Do (
%__AppDir__%where.exe /Q "%%G":*.js 1> NUL 2> NUL
If Not ErrorLevel 1 (
Echo/
Echo %%G
For /F "EOL=| Delims=" %%H In ('%__AppDir__%where.exe "%%G":*.js')Do (
Echo %%~nxH
)
)
)
) 1> "names.txt"
Pause
If you prefer to run something from the Command Prompt, then try this version:
(For /F "Delims=" %G In ('Dir /B/S/AD "C:\Project" 2^>NUL')Do #(%__AppDir__%where.exe /Q "%G":*.js >NUL 2>&1&&(Echo/&Echo %G&For /F "EOL=|Delims=" %H In ('%__AppDir__%where.exe "%G":*.js')Do #Echo %~nxH)))>"names.txt"
Two simple ways to do this:
dir /S *.js
You get the answers, just as you requested.
FORFILES /S /M *.js /C "cmd /c echo #path"
You get complete path for every file.

How to execute any .exe by using a batch file?

I know that I can start an exe by doing:
start "" /b filename.exe
But that requires me to know the name of filename.exe, how could I do that for any general file ending with .exe? I tried the obvious wildcard implementation:
start "" /b *.exe
Windows, however, gives me an error saying it cannot find "*.exe" file.
if you plan to run inside a batch file you can do in this way:
for %%i in (*.exe) do start "" /b "%%i"
if you want to skip a particular file to be executed:
for %%i in (*.exe) do if not "%%~nxi" == "blabla.exe" start "" /b "%%i"
if is necessary to check also the subfolders add the /r parameter:
for /r %%i in (*.exe) do start "" /b "%%i"
From cmd run this to the folder that has all the exe you wish to run:
for %x in (*.exe) do ( start "" /b "%x" )
Hoep it helps
for /f "delims=" %%a in ('dir /b /s "*.exe"') do (
start %%a
)
You should first use dir command to find all exe files, and then execute it.
In a bat file add this line
FOR /F "tokens=4" %%G IN ('dir /A-D /-C ^| find ".exe"') DO start "" /b %%G
This execute every .exe file in your current directory. same as
*.exe
would have done if * were supported on batch.
If you want to execute it directly from a command line window, just do
FOR /F "tokens=4" %G IN ('dir /A-D /-C ^| find ".exe"') DO start "" /b %G
Don't blame their codes for space issue. You should know how to use double quotation marks.
for /f "delims=" %%a in ('dir /b /s *.exe') do (
start "" "%%a"
)

Number of files in a directory

I'm try to find, in only one row, the number of files (*.rar) in a directory.
For doing this I'm using the commands:
for /f "delims=" %i in ('find /c ".rar" "D:\backup e ckpdb ept-icd\test\unload\lista_files_rar.txt"') do echo %i
but the value of %i I have at the end is : D:\BACKUP E CKPDB EPT-ICD\TEST\UNLOAD\LISTA_FILES_RAR.TXT: 8
I would like to obtain only the number 8 so instead to echo the value I would assign the value to a variable.
I use the command line : dir /b *.rar | find /c ".rar"
that it returns the value of rar files in the directory, but I can't assign the value to a variable, for example: dir /b *.rar | find /c ".rar" | set/a files =
I tried also to use the keyword tokens=2 but it doesn't work
p.s If it possible to do it only with the find command is also better
See here for example on counting files
Or you can simply do something like this (not tested)
for /F %%j in ('dir /B *.rar ^| find /C /V ""') do set count=%%j
This returns just the number; there might be a cleaner way to do it, but unfortuantly "find" can't take it's input from a pipe (i.e., I can't do dir | find):
#echo off
dir /b *.rar> out.tmp
for /f "usebackq tokens=3" %%i in (`find /c "rar" out.tmp`) do echo %%i
del out.tmp
Try "delims=: tokens=3"
You normally will have two colons in the result, one after the drive letter and one before the number you want, so your number should be token 3
Thank you, I think I will use
for /F %%j in ('dir /B *.rar ^| find /C /V ""') do set count=%%j
user135127
In this way I think also if somethink in the name of the dir the result should remain always the same.
which is the difference between :
dir /B *.rar ^| find /C /V "" and
dir /B *.rar ^| find /C ".rar" ?
for /f %a in ('dir "*.txt" ^| find "File(s)"') do set Count=%a
Gives
set Count=36
or you can use an arithmetic set and delayed environment variable expansion
set count=0
for %a in (*.txt) do #set /a Count=!Count!+ 1 > nul
echo %count%
gives
Count=36

Resources