Batch file to find and copy the latest file - windows

There is a system that generates a txt file dump every 15 minutes with a different file name each time. I need to find the latest file containing the text 'ASN' and copy it to a folder where I can work on it.
so far I have this, but I cannot get it to copy any file.
SET smart_server='Z:\JUL2017'
FOR /F "delims=|" %%I IN ('DIR "%smart_server%" /S /B /O:D ^| find /i "ASN" ') DO SET NewestFile=%%I
copy "%smart_server%\%NewestFile%" "C:\htdocs\smart_asn_downloads\new"
The source directory is a mapped drive I'm looking to copy it to a local drive.

The following will copy the files that contains the text ASN ignoring the case in the file itself not the file name:
#echo off
set "smart_server=Z:\JUL2017"
rem list all files (recursive) latest first
for /F "delims=|" %%I in ('dir "%smart_server%" /S /B /A-D /O:-D') do (
find /i "ASN" "%%I" > nul
rem success (errorlevel == 0)?
if not errorlevel 1 (
set "NewestFile=%%I"
)
)
if defined NewestFile (
rem addionally echoing the command due copy is not verbose
echo copy "%NewestFile%" "C:\htdocs\smart_asn_downloads\new"
copy "%NewestFile%" "C:\htdocs\smart_asn_downloads\new"
) else (
echo Found no file!
)
There are several things I've changed.
1.
set:
I changed the setting of the variable smart_server because your set contains the ' in the path.
2.
The dir command:
The sorting with /O:D would show the oldest first to reverse the list use: /O:-D. Further exclude directories to show with dir because you can't search in them with find, use: /A-D.
3.
The pipe to find:
It seems that the pipe to find does not work with spaces in a filename therefore I cut it out of the command and do it in the for loop. If the find is successful I set the NewestFile variable. I use find with /I so it ignores the case of the text.
If you need the script to copy files that contain ASN in the file name itself and ends with .txt you can use (this also ignores the case):
#echo off
set "smart_server=Z:\JUL2017"
for /F "delims=|" %%I IN ('DIR "%smart_server%\*ASN*.txt" /S /B /A-D /O:-D') DO SET NewestFile=%%I
echo copy "%NewestFile%" "C:\htdocs\smart_asn_downloads\new"
copy "%NewestFile%" "C:\htdocs\smart_asn_downloads\new"

Related

Batch script to add part of parent folder name to pdfs inside

I have a windows directory which contains folders with names like:
Lot 1
Lot 2
Lot 5
Lot A
Block A
Block C
Each of these folders contains PDF survey drawings. The names of the files are inconsequential. My goal is to prefix each PDF in ONLY LOT FOLDERS with an edited version of the name of its parent folder. Instead of adding the prefix Lot 1_ to the filenames of files in folder Lot 1 I would like to add L1_ to the filename.
Currently, I have a batch file which will add any prefix entered into a prompt to all PDFs in current folder. This means I have to go into each folder & run the batch script. This is tedious as I have thousands to deal with.
This is what the code looks like:
Set /p prefix="Enter Prefix to add to file names: "
FOR /f "delims=" %%F IN ('DIR /a-d /b *.PDF') DO (RENAME "%%F" %prefix%_"%%F")
I have been messing around trying to create a batch file to iterate through all folders with Lot and a space in their names and so far all I can do is use a for loop to get all the Lotwhatevernumber names and output them to a text file.
This is what that code looks like:
for /f "delims=" %%F in ('dir /A:D /b Lot*') do echo %%F >> folders.txt
and then I get text file with:
Lot 1
Lot 2
Lot 5
Lot A
I can also output just the number portion of the Folder name. That code:
for /f "tokens=2" %%F in ('dir /A:D /b Lot*') do echo %%F >> folders2.txt
and then I get text file with:
1
2
5
A
I felt like I was real close with that last one, but what I tried to do was instead of echoing to folders2.txt I wanted to enter another for loop where I would rename each file in Lot %%F and add a prefix of L%%F and the rest of the filename.
Anyone has any ideas?
Someone from another forum gave me this which works but the first file in each Lot folder gets named twice...I can't figure out why.
Someone on another forum provided the following which works but the first file in each Lot folder gets labelled L_ twice and I don't know why....
#echo off & setlocal
for /f "tokens=*" %%a in ('dir /b /ad lot*') do (
for %%b in ("%%a"\*.pdf) do call :xx "%%~dpb" "%%~nxb"
)
goto :eof
:xx
set z=%~1
set z=%z:~0,-1%
for %%c in ("%z%") do set k=%%~nc
set k=%k:lot =L%
echo ren %1%2 %k%_%2
ren %1%2 %k%_%2
What about this:
#echo off
rem // Switch to the target directory:
pushd "D:\Target" && (
rem /* Loop through all directories whose names begin with `Lot` + SPACE;
rem the `findstr` portion further filters the directory names so that
rem they must begin with `Lot` + SPACE + a character other than SPACE;
rem everything starting at a potential following SPACE is ignored: */
for /F "tokens=1-2" %%C in ('
2^> nul dir /B /A:D "Lot *" ^| findstr /I "^Lot [^ ]"
') do (
rem /* Loop through all `*.pdf` files in the currently iterated directory;
rem the `findstr` portion further filters the file names so that they must
rem not equal `L` + the second token from the outer loop + something containing
rem a `_` + `.pdf`, because such files are considered as already renamed: */
for /F "delims=" %%F in ('
2^> nul dir /B /A:-D "%%~C %%~D\*.pdf" ^| findstr /I /V "^L%%~D_.*\.pdf$"
') do (
rem // Check whether target file name already exists:
if exist "%%~C %%~D\L%%~D_%%F" (
rem // Collision, hence skip file and return error message:
>&2 echo Collision: cannot rename "%%~C %%~D\%%F" to "L%%~D_%%F"!
) else (
rem // No collision, so actually rename the currently iterated file:
ECHO ren "%%~C %%~D\%%F" "L%%~D_%%F"
)
)
)
rem // Return to original working directory:
popd
)
After having tested for the correct output, remove the upper-case ECHO from the ren command!

~t returning blank instead of time

I'm trying to get the name and time of the oldest file in a folder (By modification date).
I can get the name without any problem using this code
for /f "delims=" %%x in ('dir /b /o-d /a-d %currentfolder% ^| grep -v / ') do (SET FILEINFO=%%x )
From my understanding swapping the %%x for %%~tx should return the modified time instead of the filename. But I get a blank instead.
for /f "delims=" %%x in ('dir /b /o-d /a-d %currentfolder% ^| grep -v / ') do (SET FILEINFO=%%~tx )
The following code returns the time of a file in the folder but not the oldest one.
for %%a in (%currentfolder%\*) do (set LAST_TIME=%%~ta)
I tried to combine the first and last code to get the time of the oldest file but it also returns a blank.
for %%b in (%currentfolder%\%FILEINFO%) do (set MAXDATE=%%~tb)
What is the error here ? How can I solve this ?
Thank you very much for the help
You are almost there:
#echo off
set "currentfolder=D:\some directory\"
pushd "%directory%"
for /f "delims=" %%i in ('dir /b /a-d /od') do (
set "file=%%i"
set "moddate=%%~ti"
goto :done
)
popd
:done
echo %file% %moddate%
So we sort by date (oldest first) then set the first filename as %file% and it's date to %moddate% then we exit the loop so it does not do the same for the other files in the folder.
The problem is caused by the fact that your current working directory referred to by for /F is not the same as the directory you are searching files in by dir.
This can be fixed like this (omitting grep as I do not understand its purpose here):
rem // Temporarily change to the directory containing the files of interest:
pushd "%currentfolder%"
rem /* The current working directory is now the target directory;
rem thus both `dir` and `for /F` work in the same directory: */
for /F "delims=" %%x in ('dir /B /A:-D /O:-D') do (set "FILEINFO=%%~tx")
rem // Restore the former working directory:
popd
rem // Just output the gathered information:
echo/%FILEINFO%
Alternatively, the pushd command line could be replaced by cd /D "%currentfolder%" when popd is removed, given that you do not need the original working directory to be restored.
To understand what was going on in your original code, let us assume:
the current working directory is C:\TEST;
the content of variable currentfolder is D:\DATA;
the directory C:\TEST contains nothing but the batch file;
the directory D:\DATA contains a file called some.txt;
The command line dir /b /o-d /a-d %currentfolder% returns only pure file names (due to its option /B), so based on the predefined sample data, the output would be:
some.txt
Now this text is captured by the for /F loop. Now the last modification date/time is queried by %%~tx, which of course requires access to the file system. Remember that the current working directory is C:\TEST, so the for /F loop tries to gather the information from the following file:
C:\TEST\some.txt
Since such a file does not exist, the output is blank.
To prove that, simply place a new file some.txt into the directory C:\TEST, then you would receive the last modification date/time of that file.

Batch File delete newest file

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.

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.

Batch script listing files in a directory by appending to string

I am using a batch file and need to be able to list all JavaScript files found at a relative path to where the batch script is run. The final list needs to be formatted as:
"C:\path\to\file1.js" "C:\path\to\file2.js" "C:\path\to\file3.js" etc..
So far I have done:
SET files=""
FOR /f "delims=" %%i IN ('dir /b /s ".\path\to\files\*.js"') DO (
SET files=!files! "%%i"
)
ECHO Files found: %files%
However, with the script above, all I get as output is:
Files found: "" C:\path\to\last\file.js
It only outputs the last file that was found in the directory. I don't know what the issue is here as to why it only appends the last file.
Run the Batch file below exactly as appears here:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "files="
FOR /f "delims=" %%i IN ('dir /b /s ".\path\to\files\*.js"') DO (
SET files=!files! "%%i"
)
ECHO Files found: %files%
If the output is not what you want, execute the next command directly from the command-line:
dir /b /s ".\path\to\files\*.js"
If previous line show the same files than the Batch file, then the problem is related to dir command.

Resources