Windows CMD/BATCH Keep newest date stamped file - windows

I have some files that I would like to sort through and keep the newest file.
I cannot do it by file attributes date modified or created, which I could do no problem.
Here is the naming convention of the files. FileABC_YYYYMMDD.txt
FileABC_20190201.txt
FileABC_20190125.txt
FileABC_20190118.txt
FileABC_20190111.txt
FileABC_20190104.txt
You can see that the date stamp is in the filename itself. These files are generated weekly. So I'd like to have a batch file loop through them and delete all but most currently dated file. I have really searched for how to do this best and I'm not finding much so I need ideas. I prefer a pure cmd solution but I'm open to powershell solutions as well.
What I am trying on my own is to parse out the date with...
#echo off
setlocal enabledelayedexpansion
for /f "tokens=* delims= " %%G IN ('dir/b /a-d "C:\Users\thomas.maus\Documents\Tom\dev\Test Batch Files\dev\sortbyFileDateName\FileABC_*.txt"') do (
set fileName=%%G
Set theDate=!fileName:~8,8!
echo !theDate!
)
Then I want to take those dates somehow from the results of the loop and do something like
if "%theDate%" GEQ "*****not sure what to put here*****" (
del *all the old files, also not sure what to put here*
)

How about this?
#echo off
for /f "skip=1" %%i in ('dir /o-n /b *.txt') do del %%i
If you just want to test it (see what it would delete) first, do:
#echo off
for /f "skip=1" %%i in ('dir /o-n /b *.txt') do echo %%i

If you do not care about the file dates but only the dates in the file names, you could do the following, given that the part FileABC is always the same and does not contain any _ on its own:
pushd "C:\Users\thomas.maus\Documents\Tom\dev\Test Batch Files\dev\sortbyFileDateName" && (
for /F "skip=1 delims= eol=|" %%F in ('
dir /B /A:-D "FileABC_????????.txt" ^
^| sort /R
') do (
del "%%F"
)
popd
)
Although sort /R does alphabetic sorting, this works because of your chosen date format, which ensures that alphabetic order equals alphanumeric one.

We just loop through the files, sorted by date in decending order, then skip the first file, now being the latest:
#for /f "skip=1" %%a in ('dir /b /o-d *.txt') do #echo #del %%a
Important!
This example will only echo the delete command as a safe measure so you do not delete files you should not have. To perform the actual delete, remove #echo from the line.
To understand more about the functions we used, run the following from cmd.exe
for /?
dir /?

As an additional option, just in case the filename prefix changes throughout and only the _YYYYMMDD.txt remains constant, you can still peform the task using that date as it is already alphabetically sortable.
Here's an example:
#Echo Off
Set "SrcDir=%UserProfile%\Documents\Tom\dev\Test Batch Files\dev\sortbyFileDateName"
For /F "Delims==" %%A In ('Set $ 2^>Nul') Do Set "%%A="
Set "_="
For /F Delims^=^ EOL^= %%A In ('Where "%SrcDir%":*_????????.txt 2^>Nul'
) Do Set "_=%%~nA" & Call Set "$%%_:~-8%%=%%A"
If Not Defined _ Exit /B
For /F "Tokens=1* Delims==" %%A In ('Set $ 2^>Nul') Do Set "_=%%B"
For /F Delims^=^ EOL^= %%A In ('Where "%SrcDir%":*_????????.txt^|Find /V "%_%"'
) Do Del /A /F "%%A"
This uses the fact that the Set command will output variables in alphabetical order.
Lines 2 to 4 just define and undefine the variables we will be using.
Lines 5 and 6 is a single line split over two lines for readability. This will set variables using the last eight characters of the files basenames, to the value of the full filename.
Line 7 is included to exit the script, just in case no .txt files with a basename ending with an underscore followed by eight characters were found in the directory set at line 2.
Line 8 is the special one here, it outputs each variable and corresponding value in alphabetical order. The output is set to a variable, which overwrites itself until the loop ends. This means that the newest file, last one alphabetically, is held with the value of the file named with the newest date.
Lines 9 & 10 are once again a single line split over two for readability. This loops over all matching files in the directory again and uses the Find command to exclude outputting the one which matches that held in the variable as the file with the newest date. Each file output is simply deleted using the Del command.
Please note that this script assumes you only have a single file with each date, as you've only stated that the files are generated weekly.

Related

Source file name for output

I am trying to create a batch file using PDFtk to burst combine file in a certain directory to the output folder using the source file name (which can vary) as the input file name. for example
source directory :- D:\Temp\IN
destination directory :- D:\Temp\OUT
File name :- abcdefgh.pdf (which can vary)
desired output file name :- abcdefgh-001.pdf, abcdefgh-002.pdf and so on
My batch file will reside in D:\Script
The PDFtk.exe is in D:\PDFtk Server\bin
I tried for 1 whole day I can't get the input filename for the output.
Can anyone help
My existing program :-
CD D:\Temp\IN
for /f "tokens=*" %%A in ('dir /b D:\Temp\IN\*.pdf') do (
set prefix=%%~ni )
set outname=%prefix%-%%03d-00.pdf
path D:\PDFtk Server\bin
pdftk.exe D:\Temp\IN\%prefix% burst output D:\Temp\OUT\%outname%
exit
There are multiple errors in your approach the first one is that in a case like this you need local delayed expansion. For an initial % later use it as !.
CD D:\Temp\IN
This is ok but would be better if it allowed for /Drive shifting to "quoted drive folder" (beware input folder must NOT in this case be same as output folder with this approach, it is best if output is a sibling as you have done or use a common parent is better.)
CD /D "D:\Temp\IN"
for /f "tokens=*" %%A in ('dir /b D:\Temp\IN\*.pdf') do (
set prefix=%%~ni )
You have mixed up %%A and %%i they should be the same, tokens is not needed in this case but usebackq is for odd filenames and add quotes, don't need current directory, and ) is way too early.
setlocal enabledelayedexpansion
for /f "usebackq delims==" %%A in (`dir /b *.pdf`) do (
set "prefix=%%~nA"
next part
set outname=%prefix%-%%03d-00.pdf
again best quoted and needs using expansion
set "outname=!prefix!-%%03d-00.pdf"
path D:\PDFtk Server\bin
pdftk.exe D:\Temp\IN\%prefix% burst output D:\Temp\OUT\%outname%
better if combined and quoted you don't need to use Current Directory
"D:\PDFtk Server\bin\pdftk.exe" "!prefix!.pdf" burst output "D:\Temp\OUT\!outname!"
the terminal bracket goes here
)
exit
is superfluous
so all in all
CD /D "D:\Temp\IN"
setlocal enabledelayedexpansion
for /f "usebackq delims==" %%A in (`dir /b *.pdf`) do (
set "prefix=%%~nA"
set "outname=!prefix!-%%03d-00.pdf"
"D:\PDFtk Server\bin\pdftk.exe" "!prefix!.pdf" burst output "D:\Temp\OUT\!outname!"
)
The whole command could be simplified to ONE line however to show where cuts can be made
try this
CD /D "D:\Temp"
for /f "usebackq delims==" %%A in (`dir /b IN\*.pdf`) do (
"D:\PDFtk Server\bin\pdftk.exe" "IN\%%~A" burst output "OUT\%%~nA-%%03d-00.pdf"
)
the need for usebackq delims== is because of later problems with characters such as filename (1).pdf
so we cannot shorten much more than
CD /D "D:\Temp" & for /f "usebackq delims==" %%A in (`dir /b IN\*.pdf`) do ("D:\PDFtk Server\bin\pdftk.exe" "IN\%%~A" burst output "OUT\%%~nA-%%03d-00.pdf")

List all files with 2 timestamps, size, but without path or dir

Windows, Command Prompt, need to generate a .txt file output containing of all files from a big and complex dir tree with one (1) line for each files as:
CreationDateYYYYMMDD-HHMMSS, LastModifiedYYYYMMDD-HHMMSS, filesize[no K commas], filename.ext
for example:
20100101-174503, 20120202-191536, 1589567, myfile.ext
The list should not contain lines of dir name entries, etc., only filenames, even if the same file is present in more than once. Time in 24 hours format.
dir /s/t:c/t:w/-c > filelist.txt
command does not exactly works this way.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=c:\program files"
FOR /f "delims=" %%a IN (
'dir /s /b /a-d "%sourcedir%\*" '
) DO (
FOR %%d IN (timewritten timecreated) DO SET "%%d="
FOR %%k IN (-d s h) DO (
IF NOT DEFINED timewritten FOR /f "tokens=1,2 delims= " %%d IN ('dir /tw %%~k "%%a" 2^>nul ^|find "%%~nxa"') DO SET "timewritten=%%d %%e"
IF NOT DEFINED timecreated FOR /f "tokens=1,2 delims= " %%d IN ('dir /tc %%~k "%%a" 2^>nul ^|find "%%~nxa"') DO SET "timecreated=%%d %%e"
)
ECHO !timecreated! !timewritten! %%~za %%~nxa
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
Interesting problem. This code processes it by
First, applying the standard directory-list for filenames on the tree from the relative root (%sourcedir%) to %%a
Using the full filename in %%a, set timewritten and timecreated from an ordinary dir list targeting the file in question.
It appeared that %%~ta didn't play nicely to extract the timestamp for hidden and system files, so I decided to build them from the ordinary dir listing with the appropriate t setting, specifically listing with /a-d, /as and /ah and filtering for the line which matched the filename, which seemed to extract the data appropriately.
I left the date/time in raw format. It should be an easy task to extract the various elements and construct the report in the format you want.
This question is a dupe of the SO post cmd dir /b/s plus date, but posting what worked for me:
#echo off
REM list files with timestamp
REM Filename first then timestamp
for /R %I in (*.*) do #echo %~dpnxI %~tI
#echo off
REM list files with timestamp
REM Timestamp first then name
for /R %I in (*.*) do #echo %~tI %~dpnxI
The above are the versions that you would directly paste into a command prompt.
If you want to use these in a batch file and log the output, you could do something like:
rem: Place the following in a batch file such as DirectoriesBareWithTS.cmd.
rem: As the first step in the batch file, net use to the directory or share you want the listing of
rem: Change to your target directory
Y:
for /R %%I in (*.mp4) do #echo %%~tI %%~dpnxI
Then you can pipe the output to a log file when you execute:
DirectoriesBareWithTS.cmd > C:\temp\GiantLongDirListing.log
You could then import that log into Excel.

Trim Date from file name windows script

How do you trim the date from a text file. For example, I have multiple files like:
test_MX_abc_20091011.txt
test_MX_pqrdhdsu_20091011.txt
test_MX_xyieuz_20091011.txt
All files will have test_MX in common but the 3rd part will of different size.
I would like to change into:
test_MX_abc.txt
test_MX_pqrdhdsu.txt
test_MX_xyieuz.txt
I know how to change the file if name is like test_20091011.txt with the below code, But if name has more string along with date, how to do that?
for /F "tokens=1 delims=_" %%i in ("%%~na") do (
move /Y %%~fa %data_in%\%%i%%~xa >nul
)
Thanks in advance.
This rename operation can be done for example with:
#echo off
for /F "tokens=1-3* delims=_" %%A in ('dir /A-D /B test_MX_*.txt') do (
ren "%%A_%%B_%%C_%%D" "%%A_%%B_%%C.txt"
)
Each file name is separated into 4 strings assigned to loop variables A to D with using underscore as separator. The loop variable D takes everything of file name after third underscore.
Or also working for the 3 files:
#echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%F in ('dir /A-D /B test_MX_*.txt') do (
set "ActFileName=%%~nF"
set "NewFileName=!ActFileName:~0,-9!"
ren "%%~F" "!NewFileName!.txt"
)
endlocal
This solution assigns the name of a file without file extension and path to environment variable ActFileName. Next a new environment variable with name NewFileName is defined with name of active file without the last 9 characters (underscore and date string). This modified file name is used next in the rename operation.
Other solutions using commands for, set and ren can be found on Stack Overflow.
Search with the string
[batch-file] for set rename files
and more than 600 results are presented all using more or less something like above.
For details on the used commands, open a command prompt window, execute one after the other following commands and read output help.
dir /?
for /?
ren /?
set /?

Truncate filename after a multiple of a special character in windows batch script?

I want to remove the part of a filename after the third "_" from thousand of files. The structure after the third "_" varies and contains "_" in some cases. The length of the first part varies so I can't just remove the first 15 characters. The result should be unique.
The filenames look like this:
00_TEXT_=Text00._AA1234L_AA1_1.pdf
00_TEX_=Text00._AA1234L_AA1_2.pdf
00_TEXT_=TextText00._DD2023A.pdf
00_TEXT_=Text00._AA2345L_BB1_1.pdf
00_TEXT_=Text00._AA2345L_BB1_2.pdf
The result should look like this:
AA1234L_AA1_1.pdf
AA1234L_AA1_2.pdf
DD2023A.pdf
AA2345L_BB1_1.pdf
AA2345L_BB1_2.pdf
Any idea why this is not working:
#echo off
setlocal enabledelayedexpansion
set deletestring=*_*_*_
for /f "delims==" %%F in ('dir /b ^| find "%deletestring%"') do (
set oldfilename=%%F
set newfilename=!oldfilename:%deletestring%=!
Ren "!oldfilename!" "!newfilename!"
)
I was able to get it working with this:
#echo off
setlocal enabledelayedexpansion
set deletestring=*_*_*_*
for /f "tokens=1,2,3,* delims=_" %%F in ('dir /b "%deletestring%"') do (
Ren "%%F_%%G_%%H_%%I" "%%I"
)
endlocal
Note that enabledelayedexpansion isn't really needed in the above.
Alternately, you could do this as a single line (no batch file needed):
for /f "tokens=1,2,3,* delims=_" %F in ('dir /b "*_*_*_*"') do Ren "%F_%G_%H_%I" "%I"
The idea is to simply split the matching filenames apart by underscores and then reconstruct the names during the rename process (%%F_%%G_%%H_%%I gives the original file name when going through the loop). Then rename the file to everything after the 3rd underscore, which is the %%I value.
Your FINDSTR search is wrong - a string of any characters (wildcard) is .*, not *.
Variable find/replace does not support wildcards, except for the !var:*search=! syntax that replaces everthing up until the first occurrence of "search".
There is no need for FINDSTR, all you need is DIR with normal wildcard masking.
You can use FOR /F to parse the name into tokens. I use two loops - the first to get the entire name, and the second to parse out the portion after the 3rd _.
The following should work:
#echo off
for /f "eol=: delims=" %%A in (
'dir /b /a-d *_*_*_*'
) do for /f "tokens=3* delims=_" %%B in ("%%A") do ren "%%A" "%%C"
Or you could use my jren.bat utility that renames files using regular expression replacement. It is a hybrid JScript/batch script that runs natively on any Windows machine from XP onward.
jren "^(.*?_){3}" ""
Use CALL JREN if you put the command within another batch script.

Find files created/accessed/modified between dates, batch script

I need to generate lists of all files that has been created, modified and accessed respectively on a windows system.
I have found the command forfiles here http://technet.microsoft.com/sv-se/library/cc753551(v=ws.10).aspx but apparently this does not use the created and accessed timestamps, I need those also (in separate lists).
I have also looked into using the dir command but I have only found references to sorting and not filtering in the help sections.
Your question have some unclear details, so I made some assumptions.
The Batch file below create three separated text files: created.txt, modified.txt and accessed.txt, with the lists of the files in current folder; each list have the respective date in YYYYMMDDHHMMSS format followed by the file name, so it may be easily processed.
#echo off
setlocal DisableDelayedExpansion
for %%f in (created modified accessed) do if exist %%f.txt del %%f.txt
set "folder=%CD:~2%"
for /F "skip=1 tokens=1-3*" %%a in (
'"wmic datafile where (path='%folder:\=\\%\\') get InstallDate, LastModified,
LastAccessed, Name"'
) do (
for /F "delims=." %%A in ("%%a") do echo %%A %%d>> created.txt
for /F "delims=." %%B in ("%%b") do echo %%B %%d>> modified.txt
for /F "delims=." %%C in ("%%c") do echo %%C %%d>> accessed.txt
)
rem Process each list this way:
for /F "tokens=1*" %%a in (created.txt) do echo %%a - %%b
In the subject there was also "between dates" :) How about that?
forfiles doesn't allow to put 2 date conditions ('+' and '-').
I also have a problem with a date condition with unequalness in wmic.
for example:
wmic datafile where (path='%folder:\=\\\\%\\\\' and lastmodified ^> "20120713" and lastmodified ^< "20120714") get Name
returns nothing (I needed an escape ('^') before '<' and '>' to run the command).
wmic datafile where (path='%folder:\=\\\\%\\\\' and lastmodified ^> "20120713") get Name
returns only files modified after 20120714000000 (in the wmic notation).

Resources