I would like to delete everything in a folder but some files, let's say fileA.txt, fileB.exe and fileC.dll. How do I process ?
Here is what I tried, but it does not loop over all files and stops at the first, and does not even delete it :
for /R %%I in (*.*) do (
if "%%~nxI" == "fileA.txt" goto cd1
if "%%~nxI" == "fileB.exe" goto cd1
if "%%~nxI" == "fileC.dll" goto cd1
goto cd2
:cd1
goto fin
:cd2
echo HERE WE MUST DEL THE FILE !
goto fin
:fin
echo Done
)
Here is one way:
#echo off
call :hide +h
del *.*?
call :hide -h
echo done.
goto :EOF
:hide
for %%a in (
"fileA.txt"
"fileB.exe"
"fileC.dll"
) do attrib %1 "%%~a"
Generate the list, remove from it not desired files, delete the rest
for /f "delims=" %%a in (
'dir /s /b /a-d * ^| findstr /v /i /e /c:"\\filea.txt" /c:"\\fileb.exe" /c:"\\filec.dll"'
) do del "%%a"
For a longer list of exclusions, it is better to create a text file with the list of files to exclude and then use /g switch of findstr to indicate the strings.
#echo off
setlocal EnableDelayedExpansion
set exclude=/fileA.txt/fileB.exe/fileC.dll/
for /R %%I in (*.*) do (
if "!exclude:/%%~nxI/=!" equ "%exclude%" del "%%I"
)
Related
In a certain path I have some different kinds of file type. Eg., .txt, .bas, .cls, etc.
I need to delete only the text files in that path except few files.
For eg, if the path has a.txt, b.txt, c.txt, aa.bas, bb.cls, it should delete only a.txt. It should not delete b.txt and c.txt (Also it should not delete the other extension files).
To delete all ?.txt files in the root folder, excluding b.txt and c.txt
#echo off
for %%i in (?.txt) do (
if not "%%~nxi"=="c.txt" if not "%%~nxi"=="b.txt" echo del "%%i"
)
To do this in the root and subdirectories:
#echo off
for /R %%i in (?.txt) do (
if not "%%~nxi"=="c.txt" if not "%%~nxi"=="b.txt" echo del "%%i"
)
If the files are to be all *.txt files and not just single digit as per your example (add /R to recurse:
#echo off
for %%i in (*.txt) do (
if not "%%~nxi"=="c.txt" if not "%%~nxi"=="b.txt" echo del "%%i"
)
Similarly, but using findstr to only exclude:
#echo off
for /f %%i in ('dir /b /a-d ^|findstr /vi "b.txt" ^|findstr /vi "c.txt"') do (
echo del "%%i"
)
and to search only include:
#echo off
for /f %%i in ('dir /b /a-d ^|findstr /i "a.txt"') do (
echo del "%%i"
)
and to include and search subdirectories:
#echo off
for /f %%i in ('dir /b /s /a-d ^|findstr /i "a.txt"') do (
echo del "%%i"
)
On all of the above examples, remove echo to actually perform the delete, echo is used as a safety measure and will only display the del result to console.
Edit
Seeing as you specifically have a list of files (as per one of you comments) to exclude, you can use something like this. You have to create a file called exclusion.txt and add the files to exclude in list form:
b.txt
c.txt
file with space.txt
d.txt
Then create the batch file and add the code below. When ran, it will prompt for the file extention to filter on, where you can type an extension. i.e txt or simply press enter to perform a delete on all files, except the excluded ones. Just to be safe, I added an additional for loop to simply echo the files and prompt you if you are sure you want to delete the files.
#echo off
set cnt=0 & set excl= & set ext=
echo(
if not exist exclusion.txt echo You have not created an "exclusion.txt" file. & echo( & echo You need to create it first, then rerun the script & echo( & pause & goto :eof
echo Ensure you have listed all files to be excluded in "exclusion.txt" file
echo(
set /p "ext=Add File extention to search on (txt, pdf, etc), or press enter for all files: "
if not defined ext goto cont
if not "%ext:~0,1%"=="." set "ext=.%ext%"
set "ext=*%ext%"
:cont
setlocal enabledelayedexpansion
for /f "delims=" %%a in (exclusion.txt) do (
set /a cnt+=1
set "nlr!cnt!=%%a"
)
for /l %%i in (1,1,%cnt%) do (
if not defined excl (
set "excl=!nlr%%i!"
) else (
set "excl=!excl! !nlr%%i!"
)
)
echo(
echo WARNING: You are about to delete the following files!!
echo(
for /f "delims=" %%i in ('dir /b /a-d %ext% ^|findstr /VIE "%excl%"') do (
if /i not "%%i"=="exclusion.txt" if not "%%i"=="%~0" echo %%i
)
echo(
Choice /c YN /m "Are you sure you want to delete these files?"
if %errorlevel% equ 2 goto :eof
for /f "delims=" %%i in ('dir /b /a-d %ext% ^|findstr /VIE "%excl%"') do (
if /i not "%%i"=="exclusion.txt" if not "%%i"=="%~0" del %%i
)
I want to search and delete folders containing a specific string in their names, or delete all files in a folder except one, using a list of paths to browse.
Here's a working example, without the array of paths :
#echo OFF
set "sources0=%userprofile%\New folder with spaces"
set "sources1=%userprofile%\New folder with spaces 2"
set "folder1_to_delete=[test.com]"
set "folder2_name=My folder"
set "file2_to_keep=My app.lnk"
for /D /R "%sources0%" %%d in ("*%folder1_to_delete%*") do (
rem RD /S /Q "%%d" >nul
echo Found1: "%%d"
)
for /D /R "%sources1%" %%d in ("*%folder1_to_delete%*") do (
rem RD /S /Q "%%d" >nul
echo Found1: "%%d"
)
for %%i in ("%sources0%\%folder2_name%\*.*") do if not "%%~ni%%~xi" == "%file2_to_keep%" (
rem DEL /Q "%%i" >nul
echo Found2: "%%i"
)
for %%i in ("%sources1%\%folder2_name%\*.*") do if not "%%~ni%%~xi" == "%file2_to_keep%" (
rem DEL /Q "%%i" >nul
echo Found2: "%%i"
)
pause
exit
Output :
Found1: "C:\Users\marin\New folder with spaces\123 [test.com]"
Found1: "C:\Users\marin\New folder with spaces 2\456 [test.com]"
Found2: "C:\Users\marin\New folder with spaces 2\My folder\New file.txt"
But as I have many search paths, I want to iterate through an array or a list. Here's what I tried, but which doesn't work as expected :
#echo OFF
setlocal enabledelayedexpansion
set "sources[0]=%userprofile%\New folder with spaces"
set "sources[1]=%userprofile%\New folder with spaces 2"
set "folder1_to_delete=[test.com]"
set "folder2_name=My folder"
set "file2_to_keep=My app.lnk"
for /L %%n in (0,1,1) do (
set "source=!sources[%%n]!"
for /D /R "!source!" %%d in ("*%folder1_to_delete%*") do (
rem RD /S /Q "%%d" >nul
echo Found1: "%%d"
)
for %%i in ("!source!\%folder2_name%\*.*") do if not "%%~ni%%~xi" == "%file2_to_keep%" (
rem DEL /Q "%%i" >nul
echo Found2: "%%i"
)
)
pause
exit
Output :
Found2: "C:\Users\marin\New folder with spaces 2\My folder\New file.txt"
Is there a way to achieve what I want, and/or is there a better method to declare and iterate through a list or an array of paths?
Thanks!
Batch
#echo off
set folder="c:\FTP\"
set keep="keep1"
set keeptwo="keep2"
cd /d %folder%
for /F "delims=" %%i in ('dir /b') do (
if /i "%%~ni" NEQ %keep% if /i "%%~ni" NEQ %keeptwo% (rmdir "%%i" /s/q || del "%%i" /s/q)
)
pause
Situation
folder1/file1.txt
folder2/file1.txt
keep1/file1.txt
keep2/file1.txt
file1.txt
Expected result
I need to keep "keep1" and "keep2" folders and all included files, but "folder1" and "folder2" and "file1.txt" with all subdirectories and files must be deleted.
Current result
It removes all files in all folders, removes "folder1" and "folder2", and keeps "keep1" and "keep2"
Any clue what I'm missing.
You cannot use the /S option with the DELETE command as that will delete the file in the current directory and all subdirectories.
Regardless of that, this is how I would accomplish the task so that you don't get the error from the RMDIR command. I use an IF EXIST command to determine if it is a file or directory.
#echo off
set "folder=c:\FTP\"
set "keep=keep1"
set "keeptwo=keep2"
cd /d %folder%
for /F "delims=" %%G in ('dir /b') do (
if /I NOT "%%G"=="%keep%" (
if /I NOT "%%G"=="%keeptwo%" (
REM check if it is a directory or file
IF EXIST "%%G\" (
rmdir "%%G" /s /q
) else (
del "%%G" /q
)
)
)
)
I'm assuming that this is what you wanted to do:
#Echo Off
Set "folder=C:\FTP"
Set "keep=keep1"
Set "keeptwo=keep2"
CD /D "%folder%" 2>Nul || Exit /B
Del /F/A/Q *
For /D %%A In (*) Do If /I Not "%%A"=="%keep%" If /I Not "%%A"=="%keep2%" RD /S/Q "%%A"
Pause
I'm in the process of making a script that selects 25 random tracks from a user specified folder and adds them into an .m3u playlist. The trouble I have is that my music folders include various other files as well (eg: .txt, .jpg, .png, .nfo, etc...)
So I'm looking for a way of excluding the extensions listed above, limiting the script to just work with audio files. Any help would be much appreciated!
Here is the code so far... It has been stitched together from various sources so accept my apologies if it is a little crude:
#echo off
title Multiple Choice Menu
:home
cls
echo.
echo Select a genre:
echo =============
echo.
echo 1) Jungle
echo 2) D'n'B
echo 3) Reggae
echo 4) Hip-Hop
echo 5) Exit
echo.
set /p genre=Type option:
if "%genre%"=="1" cd /D "D:\NL Safe 2.0\High Quality\Jungle"
if "%genre%"=="2" cd /D "D:\NL Safe 2.0\High Quality\DnB\Standard DnB"
if "%genre%"=="3" cd /D "D:\NL Safe 2.0\High Quality\Reggae
if "%genre%"=="4" cd /D "D:\NL Safe 2.0\High Quality\Hip-Hop"
if "%genre%"=="5" exit
:: Clear existing Playlist
#echo. > C:\Users\Brew\Desktop\random.m3u
:: Create numbered list of files in a temporary file
set "tempFile=%temp%\%~nx0_fileList_%time::=.%.txt"
dir /b /s /a-d %1 | findstr /n "^" >"%tempFile%"
:: Count the files
for /f %%N in ('type "%tempFile%" ^| find /c /v ""') do set cnt=%%N
:: Open 25 random files
for /l %%N in (1 1 25) do call :openRandomFile
:: Delete the temp file
del "%tempFile%"
:openRandomFile
set /a "randomNum=(%random% %% cnt) + 1"
for /f "tokens=1* delims=:" %%A in (
'findstr "^%randomNum%:" "%tempFile%"'
) do (
setlocal EnableDelayedExpansion
set tune=%%B
#echo !tune! >> C:\Users\Brew\Desktop\random.m3u
)
Assuming your song's folder is on %1.
The dir command supports wildcards in the idea that
dir *.txt *.xml
will only list .txt and .xml files.
So you can try doing this instead:
...
:: Create numbered list of files in a temporary file
set "tempFile=%temp%\%~nx0_fileList_%time::=.%.txt"
pushd %1
dir /b /s /a-d *.mp3 *.EXT1 *.EXT2 | findstr /n "^" >"%tempFile%"
popd
...
Where EXT will be the extensions you want to match.
This will create your %tempFile% with only the files you want. Since the code that selects a file ramdomly works, as I see, over this file, it won't need to change at all.
I couldn't get dir to work with both target directory and wildcards.
Hope it helps.
This is why i used pushd and popd.
Thanks Daniel,
I had another go at it an finally got something working on my own. I used a series of If statements to put the random file through an extension validation check
This is the working script
#echo off
title Multiple Choice Menu
:home
cls
echo.
echo Select a task:
echo =============
echo.
echo 1) Jungle
echo 2) D'n'B
echo 3) Reggae
echo 4) Hip-Hop
echo 5) Exit
echo.
set /p genre=Type option:
if "%genre%"=="1" cd /D "D:\NL Safe 2.0\High Quality\Jungle"
if "%genre%"=="2" cd /D "D:\NL Safe 2.0\High Quality\DnB\Standard DnB"
if "%genre%"=="3" cd /D "D:\NL Safe 2.0\High Quality\Reggae
if "%genre%"=="4" cd /D "D:\NL Safe 2.0\High Quality\Hip-Hop"
if "%genre%"=="5" exit
:: Clear existing Playlist
#echo. > C:\Users\Brew\Desktop\random.m3u
:: Create numbered list of files in a temporary file
set "tempFile=%temp%\%~nx0_fileList_%time::=.%.txt"
dir /b /s /a-d %1 | findstr /n "^" >"%tempFile%"
:: Count the files
for /f %%N in ('type "%tempFile%" ^| find /c /v ""') do set cnt=%%N
:openRandomFile
echo opening random file.....
set /a "randomNum=(%random% %% cnt) + 1"
for /f "tokens=1* delims=:" %%A in (
'findstr "^%randomNum%:" "%tempFile%"'
) do (
setlocal EnableDelayedExpansion
set tune=%%B
FOR %%i IN ("!tune!") do call :CheckifMusic
)
:CheckifMusic
echo checking now
FOR %%i IN ("!tune!") DO (
SET fileextension=%%~xi
IF !fileextension!==.aif goto ResultTrue
IF !fileextension!==.flac goto ResultTrue
IF !fileextension!==.m4a goto ResultTrue
IF !fileextension!==.mp3 goto ResultTrue
IF !fileextension!==.wav goto ResultTrue
IF !fileextension!==.wma goto ResultTrue
echo fail
echo !fileextension!
goto openRandomFile
:ResultTrue
echo pass
echo !fileextension!
#echo !tune! >> C:\Users\Brew\Desktop\random.m3u
set /A COUNTER=COUNTER+1
IF !COUNTER!==25 (
echo finished
pause
goto Done
) ELSE (
goto openRandomFile
)
:Done
echo.
:: Delete the temp file
del "%tempFile%"
exit
)
pause
Probably not the cleanest way to do it, but hey - It works!
replace
dir /b /s /a-d %1 | findstr /n "^" >"%tempFile%"
with
dir /b /s /a-d %1 | findstr /n /L /E /I /c:".mp3" /c:".wav">"%tempFile%"
Where the /c:".mp3"... can be extended as many times as you desire to select your target filetypes.
or
with
dir /b /s /a-d %1 | findstr /n /V /L /E /I /c:".jpg" /c:".txt">"%tempFile%"
Again repeating the /c:".jpg"... as many times as you desire to select your target exclude-me filetypes.
The /i means "case-insensitive", /e means "at the end of the line" /L means "literal match, not regex" and /v means "output non-matching"
I searched extensively and found what I believe to be a solution to my problem, which is merging CSV files without duplicating headers each time. It looks like it works, except it's only copying the first file in the folder into the destination file. I think it's unable to open the files because they have a space in the name. I've been advised I probably just need to put quotes somewhere, but I'm not sure where they would go. Thanks in advance.
#ECHO OFF
SET first=y
SET newfile=new.csv
for %%F in (*.csv) do IF NOT %%F==%newfile% (
if defined first (
COPY /y "%%F" %newfile% >nul
set "first="
) else (
FOR /f "skip=1delims=" %%i IN (%%F) DO >> %newfile% ECHO %%i
)
)
#echo off
setlocal enableextensions disabledelayedexpansion
rem configure paths
set "source=*.csv"
set "target=newfile.csv"
rem remove output file if needed
if exist "%target%" del "%target%" >nul 2>nul
rem search for header row
set "headerRow="
for %%f in ("%source%") do (
<"%%~ff" ( for /l %%a in (1 1 10) do if not defined headerRow set /p "headerRow=" )
if defined headerRow goto haveHeader
)
:haveHeader
if not defined headerRow (
echo ERROR: impossible to get header row.
goto endProcess
)
rem output header to header file to use as filter.
rem header is cut to avoid findstr limitations on search strings
set "headerFile=%temp%\%~nx0_headerFile.tmp"
setlocal enableextensions enabledelayedexpansion
> "%headerFile%" echo(!headerRow:~0,125!
endlocal
rem search for input files with matching headers to join to final file
for /f "tokens=*" %%f in ('findstr /m /b /l /g:"%headerFile%" "%source%"') do (
if not exist "%target%" (
rem first file is directly copied
copy "%%~f" "%target%" /y > nul 2>nul
) else (
rem next files are filtered to exclude the header row
findstr /v /b /l /g:"%headerFile%" "%%~f" >> "%target%"
)
echo ... [%%~ff] joined to %target%
)
rem remove the temporary header file
del "%headerFile%" >nul 2>nul
:endProcess
endlocal
Here's another option.
#echo off
set "newfile=new.txt"
del "%newfile%" 2>nul
for %%a in (*.csv) do (
if not exist "%newfile%" (type "%%a" > "%newfile%") else (more +1 "%%a" >> "%newfile%")
)
ren "%newfile%" "new.csv"
#echo off &setlocal disableDelayedExpansion
set "NewFile=new.csv"
>"%NewFile%" cd .
for /f "tokens=1*delims=:" %%a in ('dir /b /a-d /od *.csv ^|findstr /nvx "%NewFile%"') do (
if %%a equ 1 (
copy /b "%%~b" "%NewFile%" >nul
) else (
for /f "skip=1delims=" %%c in ('type "%%~b"') do >>"%NewFile%" echo(%%c
)
)
sed for Windows
I think the line near the end starting "FOR /f" is mixed up and it should be:
#ECHO OFF
SET first=y
SET newfile=new.csv
for %%F in (*.csv) do IF NOT %%F==%newfile% (
if "%first%"=="y" (
COPY /y "%%F" %newfile% >nul
set "first="
) else (
FOR /f "skip=1delims=" %%i IN ("%%F") DO ECHO %%i >> %newfile%
)
)
#ECHO OFF
SET first=y
SET "newfile=new.txt"
del new.csv 2>nul >nul
for %%F in (*.csv) do (
if defined first (
COPY /y "%%F" %newfile% >nul
set "first="
) else (
FOR /f "usebackqskip=1delims=" %%i IN ("%%F") DO >> %newfile% ECHO %%i
)
)
ren %newfile% new.csv
The set "var=value" syntax ensures that any trailing spaces on the batch line are not included in the value assigned to var.
First step is to delete the new.csv file - the 2>nul >nul redirects messages and error messages from del so that the command is totally silent - whether the file exists or not.
Next, you don't need to check whether the new.csv is selected as %%F because it's just been deleed if it did exist, and the output is now to new.txt (filename not critical - actually, I'd be tempted to call it new.vsc. The critical thing is that it isn't .csv so for doesn't need to check it)
Other than the first file (a copy is faster than reading and echoing), the name of the file (in %%F) being read into %%i, since it needs to be "quoted" (to tell CMD that the spaces are not separators) you need to add the usebackq to the for/f controls.
Finally, rename your file to the desired new name.
This should fix the problem.