I want to skip the latest 3 files created and delete the rest of the files. What I need is that if there is text, xml and zip files we need to delete only the zip files and leave the text and xml files behind and the total files left should be 3.If there are 3 or more files other than .zip files, delete all .zip files; if there are less, keep the newest .zip files so that there are 3 files left in total. Can anyone help. I am stuck with this
For example(inside bracket created date of files):
Folder A contains - aa.txt(2/1/18), bb.xml(3/1/18), cc.zip(4/1/18), dd.zip(2/1/18),ee.zip(5/1/18)
What I need after deleting is
aa.txt, bb.xml, ee.zip
This is what I have written
#ECHO OFF
SETLOCAL
SET "targetdir=C:\source"
SET /a retain=3
FOR /f "skip=%retain%delims=" %%a IN (
'dir /b /a-d /o-d "%targetdir%\*.zip" '
) DO DEL (DEL "%targetdir%\%%a.zip"
GOTO :EOF
Given the parameters of your question, a very simple method, although not the most efficient or speedy, would be to do this:
#Echo Off
Set "targetdir=C:\source"
Set "retain=3"
CD /D "%targetdir%" 2>Nul || Exit /B
For /F "Skip=%retain% Delims=" %%A In ('Dir /B/A-D/O-D/TC'
) Do If /I "%%~xA"==".zip" Del "%%A"
Related
I have a huge folder that I would like to transform into several small ones of 20 files each and compressed. I would like to do this automatically with a batch file and 7zip.
To achieve this I thought about 2 steps:
1. Create a sub-folder for each 20 files (source) :
#echo off
set /a counter=1
set /a filesperfolder=20
cd "C:\Users\Desktop\dir\"
:loopstart
set dirname=dir_%counter%
md %dirname%
echo %dirname%
dir /b | findstr /v /i "dir_*"> %temp%\temp.txt && for /l %%l in (1,1,%filesperfolder%) do #for /f "tokens=1,2* delims=:" %%a in ('findstr /n /r "^" %temp%\temp.txt ^| findstr /r "^%%l:"') do #move %%b %dirname%\%%b >nul
set /a counter=%counter%+1
for /f "tokens=*" %%a in ('type %temp%\temp.txt ^| find /c /v ""') do set _filesmoved=%%a
del %temp%\temp.txt
IF %_filesmoved% LSS 20 goto done
goto loopstart
:done
cls
echo All files were moved!!
pause
exit
Unfortunately this does not work : The syntax of the command is incorrect.. I've tried debugging the script by removing the #echo off and it tells me that the dir /b | findstr /v /i "dir_*"> %temp%\temp.txt && for /l %%l in (1,1,%filesperfolder%) do #for /f "tokens=1,2* delims=:" %%a in ('findstr /n /r "^" %temp%\temp.txt ^| findstr /r "^%%l:"') do #move %%b %dirname%\%%b >nul part is not working (same error). This part is quite fuzzy for me and a little help would be welcome.
I specify that the file temp.txt contains my complete list of files, without any separator (one file per line).
--- UPDATE: filenames must not contain spaces ---
2. Compress all these subfolders one by one with (source) :
for /D %d in (*.*) do 7z a -tzip "%d.zip" ".\%d\*"
Do you have an idea for (I summarize) : create, for a large number of files, subfolders of 20 files in order to compress each subfolder one by one.
If you have any idea on how to compress each 20 files directly (without going through the creation of subfolders) I also agree!
Thank you in advance for your help!
Resolved!
I found my mistake. In reality my files included spaces that the script could not fit.
So, to answer my basic question which was: in a big folder filled with thousands of files, how to compress each 20 files in subfolders? it is necessary (to my knowledge) to:
Create a sub-folder for each 20 files whose name does not have spaces (code in my question)
Compress all these subfolders one by one (code in my question)
And it's done!
Do not hesitate to suggest a solution if you know of a "faster" one.
No need to create folders. Just iterate over the files and add every single file to it's designated zip file (instead of copying every 20 files into a folder and zip that folder)
Use two counters to keep track of (source)files and zip files. One counter for the files (use the Modulo-operator to check for each 20) and one for the zip filenames. I started the zip filenames with 10001 instead of 1 and took the last four chars of it to get sortable file names (0001.zip etc).
#echo off
setlocal enabledelayedexpansion
set filesperfolder=20
cd /d "%cd%"
set "zipDest=C:\temp"
set filecounter=0
set foldercounter=10001
for %%a in (*) do (
set /a filecounter+=1
set /a check=filecounter %% filesperfolder
if !check! == 0 set /a foldercounter+=1
ECHO 7z a -tzip "%zipDest%\!foldercounter:~-4!.zip" "%%a"
)
Obviously adapt the cd /d line (source folder), destination folder (Attention: don't use the source folder, or your zip files might be zipped again into other zip files), and maybe the zip-filename (like "%zipDest%\MyZips-!foldercounter:~-4!.zip")
NOTE: I disarmed the 7zip command with ECHO for testing and troubleshooting. Remove the ECHO when the output satisfies you.
To delete each file after successfully zipping them, change the zip line to:
7z a -tzip "%zipDest%\!foldercounter:~-4!.zip" "%%a" && del "%%a"
The quotes should take care of any spaces.
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
How do you all delete the newest file in a folder using batch script?
All results I have found ONLY show how to delete the oldest files or delete them after N days.
Links are : Batch file to delete files older than N days and Batch Script to delete oldest folder in a given folder
Thank you
for /F %%a in ('dir /B /O-D /A-D %the_directory%') do echo("%the_directory%\%%a"&goto deldone
:deldone
would be my approach. It rudely escapes from the for loop having deleted the first filename encountered in a sorted-in-reverse-date-order (/o-d) list.
This saves having to read the entire list. Not such a problem with a few files, but can be a pain with thousands.
The required DEL command is merely ECHOed for testing purposes. After you've verified that the command is correct, change ECHO(DEL to DEL to actually delete the files.
I would do this:
#echo off
set latest=
set the_directory=your_directory
for /F %%a in ('dir /B /OD /A-D %the_directory%') do set latest=%%a
del %the_directory%\%latest%
run dir on files only, with sorting on modification date. Then loop and keep last echoed file. Delete it (replace by echo to test!)
The following code snippet does what you want:
set "FILE="
pushd "\path\to\folder" || exit /B 1
for /F "eol=| delims=" %%F in ('
dir /B /A:-D /O:D /T:C "*.*"
') do (
set "FILE=%%F"
)
if defined FILE del "%FILE%"
popd
The dir command returns files only (/A:-D) sorted by date in ascending order (/O:D) using the creation date (/T:C), which are located in \path\to\folder and match the pattern *.*.
The for /F loop walks through all the files returned by dir and assigns its name to variable FILE, overwriting it in each iteration, hence the final value is the name of the newest file.
The del command finally deletes the found file. The if query covers the case when no files are found in the given location.
Here is a slightly modified variant as recommended by Magoo's comment, which might be a bit more performant than the aforementioned one:
set "FILE="
pushd "\path\to\folder" || exit /B 1
for /F "eol=| delims=" %%F in ('
dir /B /A:-D /O:-D /T:C "*.*"
') do (
if not defined FILE set "FILE=%%F"
)
if defined FILE del "%FILE%"
popd
This avoids multiplicately overwriting of variable FILE by querying whether it has already been defined. Note the reversed sort order of dir here.
However, the approach shown in Magoo's answer is still better in performance.
Here's what I have;
On a windows-based web server there are roughly 1,000 zip files, each with dozens of log files inside. I already have a script that goes through each archive and deletes all but one specific file type (in an attempt to save diskspace and delete things I don't need). Then, the script unzips each archive to their own folder. And I know how to code the reverse of that to zip them back when I'm done.
Here's what I need to figure out;
Once I run the previously mentioned script (we call it garbageman because it cleans out the garbage in the zip files) I need to go through the remaining 5 or 6 files in each of the newly created unzipped folders, and look for a specific string in each file. If I find the string, I delete everything that is not that string, and save it to a file called "export.txt" in that folder. Then, I move to the next unzipped file, and so on. Once completed, I need re-zip everything back together into their own archives
Here's what I have for code so far. Any help is extremely appreciated.
cd "C:\Program Files\7-Zip"
FOR %%c in (C:\Users\xxxxxx\Desktop\LogQueue\*.*) DO 7z d %%c "-x!xstore*" -r
FOR /R "C:\Users\xxxxxx\Desktop\LogQueue" %%I in ("*.zip") do (
"%ProgramFiles%\7-Zip\7z.exe" x -y -o"%%~dpnI" "%%~fI"
)
cd "C:\Users\xxxxxxx\Desktop\LogQueue"
FOR /R "C:\Users\xxxxxx\Desktop\LogQueue" %%I in ("*.*") do (
findstr "xxxxxxxx_eReceipt" %%~fI > %%~dpnI\export.txt
pause
)
for /d %%X in (*) do "c:\Program Files\7-Zip\7z.exe" a "%%X.zip" "%%X\"
This is an edit:
This script should do what you want.
Only Change sourcedir and mystring variables.
export.txt will be inside a file called Storage in the root directory of the batch.
:ScriptA
#ECHO ON
MKDIR "%CD%\Storage"
MKDIR "%USERPROFILE%\Desktop\Outx"
GOTO :ScriptB
:ScriptB
::REM ONLY CHANGE
SET "sourcedir=%USERPROFILE%\Desktop\Test"
FOR /R "%sourcedir%\" %%a in (*.txt) do copy "%%a" "%CD%\Storage"
:ScriptC
:ScriptC
#ECHO OFF
SETLOCAL
SET "VARA=%CD%\Storage"
SET "VARB=%USERPROFILE%\Desktop\Out"
::REM ONLY CHANGE
SET "mystring=PUT_STRING_HERE"
FOR %%a IN ("%VARA%\*.txt") DO FINDSTR "%mystring%" "%%a">nul&IF NOT ERRORLEVEL 1 FINDSTR "%mystring%" "%%a">"%VARB%\%%~nxa"
DEL /F "%CD%\Storage\*.txt"
GOTO :ScriptD
:ScriptD
#ECHO ON
COPY /B "%USERPROFILE%\Desktop\Outx\*.txt" "%CD%\Storage\export.txt"
RD /S /Q "%USERPROFILE%\Desktop\Outx"
goto :eof