Finding a latest folder that contains a specific file - batch-file

I need to search a directory with multiple folders and check for the latest file(.exe) and copy that to another location.
SET "src_root"
SET "tgt_path"
DIR "%src_root%" /B /AD /O-D /TC > "%TEMP%\dirlist.tmp"
< "%TEMP%\dirlist.tmp" SET /P last_dir=
XCOPY "%src_root%\%last_dir%\*.exe" "%tgt_path%"**
This code helps me copy the EXE file in the latest folder, but in case, there is no EXE in the latest folder, I need to copy it from the folder which contains the latest EXE, can anyone help me out?

#ECHO OFF
SETLOCAL
SET "sourcedir=c:\sourcedir"
SET "filename="
FOR /f "delims=" %%a IN (
'dir /s /b /a-d "%sourcedir%\neo.7z" '
) DO SET "filename=%%a"&set "dirname=%%~dpa"&goto found1
ECHO NOT found!
GOTO :eof
:found1
FOR /f "delims=" %%a IN (
'dir /s /b /a-d "%sourcedir%\neo.7z" '
) DO IF /i "%dirname%" neq "%%~dpa" FOR /f %%s IN ('XCOPY /y /L /D "%filename%" "%%~dpa"') DO IF "%%s"=="0" SET "filename=%%a"&set "dirname=%%~dpa"&goto found1
ECHO latest file is "%filename%"
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used files named neo.7z for my testing - I believe that you should have a fixed filename in the situation you describe - the directories are no doubt not crammed with *.exe files.
It's very pedestrian, but will do the job.
Essentially, find any file with the required name in the required directory-tree and record the name in filename, directory in dirname.
Using that filename as a base, try xcopying it over every other matching filename. Use the /L flag to list-only, and the /y flag to remove user-intervention. If the return is 1 file(s) copied ,f which only the first token is selected into %%s, then the chosen file is later. 0 file(s) copied sets %%s to 0 and means that the chosen file is earlier, so select the newer file and directorynames and restart.
I'll leave it a a user-exercise to speed it up. (suggestions if interested : delayedexpansion, subroutine and retain-new-startpoint)
Revision [about 5 times faster]
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\sourcedir"
SET "filename="
FOR /f "delims=" %%a IN (
'dir /s /b /a-d "%sourcedir%\neo.7z" '
) DO SET "candidate=%%a"&CALL :latest
ECHO latest file is "%filename%"
GOTO :eof
:latest
IF NOT DEFINED filename GOTO selectnew
FOR /f %%s IN ('XCOPY /y /L /D "%filename%" "%candidate%"') DO IF "%%s"=="1" goto :eof
:selectnew
SET "filename=%candidate%"
GOTO :EOF
This revision avoids the repetitive directory-scan. For each matching filename, compare the newly-found file against the previously-found file using the xcopy /L method, and select the new candidate if the new one is later. continue untill all matching names have been tested.

Related

Delete all files except filenames with specific string

I have 1000's of files like TOP_QUERIES-abc.com.au.csv,TOP_QUERIES-www.abc.com.au.csv, TOP_QUERIES-m.lmn.com.au.csv, TOP_QUERIES-blog.com.au.csvand get-files.php
Is it possible to delete all the .csv files from a folder except for files starting with blog. ,m. , www, and .php from the folder?
I know its possible in php but how can I achieve in batch file?
#ECHO OFF
SETLOCAL
SET "targetdir=U:\destdir"
SET "exclude=blog. m. www."
FOR /f "delims=" %%a IN (
'dir /b /a-d "%targetdir%\*.csv" '
) DO (
ECHO %%a | findstr /B /L "%exclude%" >NUL
IF ERRORLEVEL 1 ECHO(DEL "%targetdir%\%%a"
)
GOTO :EOF
This should get the task done for you. You would need to change the setting of targetdir to suit your circumstances.
The required DEL commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(DEL to DEL to actually delete the files.
The .php files are excluded because they don't match the *.csv filename - or did you want to not-delete files starting .php? If so, simply add .php into the exclude variable...
Revision for efficiency:
#ECHO OFF
SETLOCAL
SET "targetdir=U:\destdir"
SET "exclude=blog. m. www."
FOR /f "delims=" %%a IN (
'dir /b /a-d "%targetdir%\*.csv" ^| findstr /B /L "%exclude%"'
) DO (ECHO(DEL "%targetdir%\%%a"
)
GOTO :EOF

Batch File to Loop Through Folders and Copy Folder & Contents to Directory with Same Folder Name

Each month, corporate dumps (saves) a varying number of files into a varying number of folders on a shared network drive. The files contain information, in either an .xlsx or .pdf file format, and the folders represent different projects. The folder names consist of the project number only (i.e. 12345, 15241-0001,16755-0004, etc...). Typically a five digit number or five digit number followed by a hyphen and then a four digit number.
I would like to be able to create a batch file that can be ran to loop through the folders that corporate dumps to the shared network share drive and then copies the project folder and contents (files) to a different shared network drive that contains the corresponding project folders used by operations in my department. The project folder names on the operations shared network drive contain the project number, a space, a hyphen, another space, and then the project name (i.e. 12345 - Project 1, 15241-0001 - Project 22, 16755-0004 - Project 12, etc...)
Update...
Magoo you have been spot-on and a great help, as I am learning from your posts. I failed to take into account is that the sub-projects on the operations side are all in main-project folders:
u:\destdir\2015\15241\15241-0001 - Project 06
u:\destdir\2015\15241\15241-0001 - Projekt 60
u:\destdir\2016\16755\16755-0004 - Project 14
So the script does not copy the files to the sub-projects as the script believes the destination does not extist. Is it possible to get the first five characters of the project and insert into the destination directory of the xcopy command?
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN (
'dir /b /ad "%sourcedir%\*" '
) DO (
FOR /f "delims=" %%b IN (
'dir /b /ad "%destdir%\%%a*" '
) DO (
ECHO(XCOPY /s "%sourcedir%\%%a\*" "%destdir%\%%b\"
)
)
GOTO :EOF
You would need to change the setting of sourcedir and destdir to suit your circumstances.
The required XCOPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(XCOPY to XCOPY to actually copy the files.
Edit : revision in the light of futher half-information.
Assuming the destination structure is ...\2012\12???(-?????) - waffle then
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN (
'dir /b /ad "%sourcedir%\*" '
) DO CALL :process "%%a"
GOTO :EOF
:process
SET "year=%~1"
SET /a year=20%year:~0,2%
SET "copied="
FOR /f "delims=" %%b IN (
'dir /b /ad "%destdir%\%year%\%~1*" 2^>nul'
) DO IF DEFINED copied (ECHO %1 NOT copied to duplicate destination "%destdir%\%year%\%%b\"
) ELSE (
SET "copied=%destdir%\%%b\"
ECHO( XCOPY /s "%sourcedir%\%~1\*" "%destdir%\%year%\%%b\"
)
)
IF DEFINED copied (ECHO %1 WAS copied to destination "%copied%"
) else (ECHO %1 WAS NOT copied - no destination found)
GOTO :EOF
You would need to change the setting of sourcedir and destdir to suit your circumstances.
Test results:
Destination directory structure
u:\destdir\2012
u:\destdir\2015
u:\destdir\2016
u:\destdir\2012\12345 - Project 98
u:\destdir\2015\15241-0001 - Project 06
u:\destdir\2015\15241-0001 - Projekt 60
u:\destdir\2016\16755-0004 - Project 14
Process output:
XCOPY /s "U:\sourcedir\t w o\12345\*" "U:\destdir\2012\12345 - Project 98\"
"12345" WAS copied to destination "U:\destdir\12345 - Project 98\"
XCOPY /s "U:\sourcedir\t w o\15241-0001\*" "U:\destdir\2015\15241-0001 - Project 06\"
"15241-0001" NOT copied to duplicate destination "U:\destdir\2015\15241-0001 - Projekt 60\"
"15241-0001" WAS copied to destination "U:\destdir\15241-0001 - Project 06\"
XCOPY /s "U:\sourcedir\t w o\16755-0004\*" "U:\destdir\2016\16755-0004 - Project 14\"
"16755-0004" WAS copied to destination "U:\destdir\16755-0004 - Project 14\"
"13234-1234" WAS NOT copied - no destination found
Note that the xcopy lines are indented for ease-of-separation.
Hyphens work for me!
Revision to proess exclude list - on the assumption that the exclude-list will be shorter than the include-list (2 line change - add the exclude-list set and process that list.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"
SET "excluding=16755-0004"
FOR /f "delims=" %%a IN (
'dir /b /ad "%sourcedir%\*" '
) DO CALL :process "%%a"
GOTO :EOF
:process
FOR %%x IN (%excluding% dummy) DO IF "%~1"=="%%x" ECHO %1 WAS NOT copied - excluded&GOTO :EOF
SET "year=%~1"
SET /a year=20%year:~0,2%
SET "copied="
FOR /f "delims=" %%b IN (
'dir /b /ad "%destdir%\%year%\%~1*" 2^>nul'
) DO IF DEFINED copied (ECHO %1 NOT copied to duplicate destination "%destdir%\%year%\%%b\"
) ELSE (
SET "copied=%destdir%\%%b\"
ECHO( XCOPY /s "%sourcedir%\%~1\*" "%destdir%\%year%\%%b\"
)
)
IF DEFINED copied (ECHO %1 WAS copied to destination "%copied%"
) else (ECHO %1 WAS NOT copied - no destination found)
GOTO :EOF
Note the inclusion of dummy to ensure that the list in the for %%x loop is not empty.
And for the next requirement ("project" level in directory) One more line - but I commened-out the excluding line for ease-of-testing.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"
REM SET "excluding=16755-0004"
FOR /f "delims=" %%a IN (
'dir /b /ad "%sourcedir%\*" '
) DO CALL :process "%%a"
GOTO :EOF
:process
FOR %%x IN (%excluding% dummy) DO IF "%~1"=="%%x" ECHO %1 WAS NOT copied - excluded&GOTO :EOF
SET "year=%~1"
SET /a year=20%year:~0,2%
FOR /f "tokens=1,2delims=-" %%x IN (%1) DO IF NOT "%%y"=="" SET "year=%year%\%%x"
SET "copied="
FOR /f "delims=" %%b IN (
'dir /b /ad "%destdir%\%year%\%~1*" 2^>nul'
) DO IF DEFINED copied (ECHO %1 NOT copied to duplicate destination "%destdir%\%year%\%%b\"
) ELSE (
SET "copied=%destdir%\%%b\"
ECHO( XCOPY /s "%sourcedir%\%~1\*" "%destdir%\%year%\%%b\"
)
)
IF DEFINED copied (ECHO %1 WAS copied to destination "%copied%"
) else (ECHO %1 WAS NOT copied - no destination found)
GOTO :EOF
year now no longer contains just the year, but possibly the next lower directory level (project) if the filename provided contains a subproject.

How to batch file to create folder from part of file name and move files

Batch file to create folder from part of file name and move files.
I have lots of files that need to be in their own sub folder.
They are in this format:
Example
123456-ABC-XYZ
123456-DFG-XYZ
123456-HIJ-XYZ
Where I would like to create a sub folder and move the files to it by characters 8-10
or by 12-14
Used this as a base that I found on this site posted by Magoo
and it works to do it by the 1st set of characters (h:\1AAATEST = my test folder
#ECHO OFF
SETLOCAL
SET "sourcedir=h:\1AAATEST"
PUSHD %sourcedir%
FOR /f "tokens=1*" %%a IN (
'dir /b /a-d "*_*_*-*-* *.*"'
DO
(MD %%b MOVE "%%a %%b" .\%%b\)
POPD
GOTO :EOF
[Editing note from Magoo:
This is incorrect. Here's what I posted:
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\sourcedir"
PUSHD %sourcedir%
FOR /f "tokens=1*" %%a IN (
'dir /b /a-d "*_*_*-*-* *.*"'
) DO (
ECHO MD %%a
ECHO MOVE "%%a %%b" .\%%a\
)
POPD
GOTO :EOF
reference: Question from nearly a year ago
Notice that there are major difference beyond the change of source directory and omission of the echo keyword as narrated. OP's syntax in this question simply won't work.
]
I modified it with the same results as the original
#ECHO OFF
SETLOCAL
SET "sourcedir=h:\1AAATEST"
PUSHD %sourcedir%
FOR /f "tokens=1*" %%a IN (
'dir /b /a-d "*-*-*.*"'
) DO (
MD %%a
MOVE "%%a %%b" .\%%a\
)
POPD
GOTO :EOF
Then again, and it created 4 folders from this file name
LAST_FIRST_7-24-1936 Diagnostic - Topography 11-18-10_1
But didn't move any files.
1st folder = -
2nd = 11-18-10_1
3rd = Diagnostic
4th = Topography
#ECHO OFF
SETLOCAL
SET "sourcedir=h:\1AAATEST"
PUSHD %sourcedir%
FOR /f "tokens=1*" %%a IN (
'dir /b /a-d "*-*-*.*"'
) DO (
MD %%b
MOVE "%%a %%b" .\%%a\
)
POPD
GOTO :EOF
I came up with the following:
#echo off
for /f "tokens=1-3* delims=-," %%a in ('dir /b /a-d "*-*-*"') do (
(md "%%~nb" 2>nul)
(MOVE "%%a-%%b-%%c" "%%b"))
POPD
GOTO :EOF
It works for making directory and moving files for the 1st and 2nd section of the file name,
by changing the md to a & the move target dir to a for 1st part of file name &
by changing the md to b & the move target dir to b for 2nd part of file name &
BUT changing the md to c & the move target dir to c for 3rd part of file name &
DOESN"T work. It creates the correct dir, and it doesn't move the files but it shortens the filenamnes to XYZ.
Suggestions would be appreciated.
I received an angry telephone call one day from someone who'd used a library I published and it had a major fault. In reality, it had been modified and republished by someone with no note as to who, when or why in the library source. That was the last time I ever published sourcecode for my commercial work.
The problem you are encountering is very simply explained.
The for /f examines LAST_FIRST_7-24-1936 Diagnostic - Topography 11-18-10_1 and assigns LAST_FIRST_7-24-1936 to %%a and Diagnostic - Topography 11-18-10_1 to %%b
In the code as you have modified it, you are then executing MD %%b which will be interpreted as
MD Diagnostic - Topography 11-18-10_1
so batch creates those four directories, as requested.
Then the move is encountered. The destination directory is .\%%a\ which will attempt to move the file to .\LAST_FIRST_7-24-1936\ - a directory which is unlikely to exist.
So - to fix the problem, try replacing MD %%b with MD %%a as was specified in the original code.
As for your requirement for 123456-ABC-XYZ, then try
#ECHO OFF
SETLOCAL
SET "sourcedir=h:\1AAATEST"
PUSHD %sourcedir%
FOR /f "tokens=1,2,*" %%a IN (
'dir /b /a-d "*-*-*"'
) DO (
MD %%b
MOVE "%%a-%%b-%%c" .\%%b\
)
POPD
GOTO :EOF
(this version to move to the directory with the middle block of characters - to move to the end-block, replace %%b with %%c in both the MD command and the destination of the move command)
BTW - it's very likely that the md will complain about attempting to create an existing directory. You can shut it up by appending 2>nul to the end of the md command.

Partial path known..need to search for file type inside

There is a particular folder that begins with a name such as SS followed by random characters. The names would be different every time and the only thing we are sure of is the folder begins with SS. How do we look if this folder has a .txt file inside in batch programming.
An idea :
#echo off
for /f "delims=" %%a in ('dir /b/ad ^|find /i "SS"') do set $Dir=%%a
dir /b/a-d *.txt %$dir%>nul
if %errorlevel% equ 0 echo File(s) found in "%$DIR%"
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN (
'dir /b /ad "%sourcedir%\ss*" 2^>nul'
) DO (
FOR /f "delims=" %%h IN (
'dir /b /a-d "%sourcedir%\%%a\*.txt" 2^>nul'
) DO (
ECHO "%sourcedir%\%%a\%%h"
)
)
GOTO :EOF
should solve your problem - you need to change sourcedir to suit your system, obviously.
The code below check if the folder contain any .txt file:
#echo off
set "filePath="
for /D %%a in (SS*) do if exist "%%a\*.txt" do set "filePath=%%a"
if defined filePath echo File exists in folder %filePath%
If you want to check for a particular .txt file, just change *.txt by the appropriate name.

create folders based on string in file name

I need a batch file to create a process for a list of files in a directory.
The filename structure is, for example: 00000_AAA_132144_2012021.txt
I need the batch to:
1 - Create a folder name based on the numbers after the second underscore, as this is the only constant in the naming.
2 - Move the file into the new folder.
In the example of the above the batch would create a folder called 132144 and then move the file 00000_AAA_132144_2012021.txt into the folder
For a similar requirement I used the script Endoro created for me (below). Is it possible to modify this to meet my requirement?
#echo off &setlocal
for /f "delims=" %%i in ('dir /b /a-d *.PDF') do (
set "filename1=%%~i"
setlocal enabledelayedexpansion
set "folder1=!filename1:~11,6!"
mkdir "!folder1!" 2>nul
move "!filename1!" "!folder1!"
endlocal
)
If you know that the filenames will be the same length, you can do the following to get the numbers after the second underscore -
set filename=00000_AAA_132144_2012021.txt
set dirname=%filename:~10,6%
If the spacing may vary - you can do the following -
for /f "delims=_ tokens=3" %%a in ('echo %filename%') do set dirname=%%a
And yes, the script written for you seems to do essentially the same thing as what you're asking - I've edited it to do what you've asked -
#echo off
setlocal enabledelayedexpansion
for /f %%i in ('dir /b /a-d *.txt') do (
set "filename=%%~i"
for /f "delims=_ tokens=3" %%a in ('echo !filename!') do set folder=%%a
mkdir "!folder!" 2>nul
move "!filename!" "!folder!"
)
This will move all *.txt documents to a folder created based on the third section of the text files name. Note that this will cause problems if you have .txt documents in the directory that do not follow the same naming standard.
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\sourcedir"
SET "destdir=c:\destdir"
FOR /f "delims=" %%a IN ('dir /b /a-d "%sourcedir%\*_*_*_*.txt" ') DO (
FOR /f "tokens=3delims=_" %%m IN ("%%a") DO (
ECHO MD "%destdir%\%%m"
ECHO MOVE "%sourcedir%\%%a" "%destdir%\%%m\"
)
)
GOTO :EOF
Endoro's routine selects .pdf files, you've specified .txt
Find filenames matching the mask, find the third _-separated token in the name, make that directory and then move the file.
The required commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO MD to MD to actually create the directories and change ECHO MOVE to MOVE to actually move the files.
Append 2>nul to suppress error messages (eg. when the directory already exists)
Append >nul to suppress report messages (eg. 1 file moved)

Resources