Searching all the existance of particular file with Batch - windows

am struggling through these crewl batch cmds from quite long.
I need to search file (actually the installation folder of some software (XYZ) (I know there is a way to check that in registry
but I wanted an easy way to check some ABC.cmd file; if that exist give me the path of that file;
but the problem is that file also exist at various places and giving me the wrong answer.
Can some body please tell me so It can give me all file existence in least time and then I could select which I want to select with batch script.
this is my current code but It's giving the first one which it found and not my desired one:
#echo off
FOR /f "Tokens=*" %%i in ('DIR \stDesign.cmd /B /S /a-d') do (set PATH="%%~dpi")
FOR /f "Tokens=*" %%i in ('DIR \stDesign.cmd /od /b /S') do (set URL="%%~dpi")
thanks.

Well, first /a-d and /od are not switches for dir. I believe that you meant /a:d and /o:d respectively.
Apart from those errors the reason your first for statement doesn't work is because DIR \stDesign.cmd /B /S /a:d is searching for directories* called stDesign.cmd, not files.
Your second for statement is telling DIR to order the files by their creation date, but that only works for files inside the same directories, not across directories. Meaning that any matching files inside the same directory will be sorted by date, but files that exist inside seprate directories will be in the ordered that DIR found them.
Try
#echo off
echo.
REM Housekeeping: Delete any existing files left-over from previous runs
if exist "%tmp%\~.tm?" del "%tmp%\~.tm?"
REM Find the files
for %%v in (*.bat) do (
REM Extract Date, Time, Path, File Name, and Extention
for /f "tokens=1-3* delims=/ " %%w in ("%%~tdpnxv") do (
REM Change the date around so that simply sorting the lines
REM will order them by date and time.
echo %%y/%%w/%%x %%z>>%tmp%\~.tmp
)
)
REM Sort (in ascending order) and Display data
type "%tmp%\~.tmp" | sort
REM Housekeeping
del "%tmp%\~.tmp"
echo.
REM Or, if you don't want to display the time and date, replace the type line with:
#echo off
echo.
REM Housekeeping: Delete any existing files left-over from previous runs
if exist "%tmp%\~.tm?" del "%tmp%\~.tm?"
REM Find the files
for %%v in (*.bat) do (
REM Extract Date, Time, Path, File Name, and Extention
for /f "tokens=1-3* delims=/ " %%w in ("%%~tdpnxv") do (
REM Change the date around so that simply sorting the lines
REM will order them by date and time.
echo %%y/%%w/%%x %%z>>%tmp%\~.tmp
)
)
REM Sort (in ascending order) and save data to ~.tm2
type "%tmp%\~.tmp" | sort >> "%tmp%\~.tm2"
REM Extract path and file name only from ~.tm2 and display it
for /f "tokens=4* usebackq" %%x in ("%tmp%\~.tm2") do echo %%x
REM Housekeeping
del "%tmp%\~.tmp"
echo.
The first example gives an output like this:
1992\01\15 00:12:55 C:\SOMEPATH\FILE0001.EXT
2004\04\17 00:42:17 C:\ANOTHERPATH\FILE0002.EXT
2004\04\17 12:42:17 C:\MISCPATH\RANDOM\FILE0003.EXT
2012\10\15 00:12:55 C:\EXAMPLE\FILE0004.EXT
2012\01\15 00:12:55 C:\FILE0005.EXT
The 2nd example displays only the path and file names, but still ordered by date + time.
C:\SOMEPATH\FILE0001.EXT
C:\ANOTHERPATH\FILE0002.EXT
C:\MISCPATH\RANDOM\FILE0003.EXT
C:\EXAMPLE\FILE0004.EXT
C:\FILE0005.EXT
To reverse the sort order, use the /R switch with sort, like so:
type tmp.txt | sort /R
*Directories and Folders are the same thing.

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.

Generate a list of the newest file in each subdirectory in windows batch

I have a need to determine what the newest file is in each subdirectory under a root folder and output that list to a text file showing both the filename and creation date. As an example, if the root directory is D:\Data which contains a total of 4 subdirectories, and one of those 4 contain a subdirectory, my output file should contain a list of only files (not including created folders) something like this:
D:\Data\folder1\filename 02/12/14
D:\Data\folder2\filename 03/02/14
D:\Data\folder3\filename 03/15/14
D:\Data\folder4\folder01\filename 01/22/14
I have checked other posts, but none seem do this specifically...
Two options
#echo off
setlocal enableextensions enabledelayedexpansion
set "rootFolder=c:\somewhere"
:: option 1
echo --------------------------------------------------------------------------------
for /d /r "%rootFolder%" %%a in (.) do (
set "first="
for /f "delims=" %%b in ('dir /o-d /a-d /b "%%~fa\*" 2^>nul') do if not defined first (
set "first=1"
for %%c in ("%%~fa\%%b") do echo %%~tc %%~fc
)
)
:: option 2
echo --------------------------------------------------------------------------------
set "tempFile=%temp%\%~nx0.%random%.tmp"
dir /a-d /b /s /o-d "%rootFolder%" 2>nul >"%tempFile%"
set "oldFolder="
for /f "usebackq delims=" %%a in ("%tempFile%") do if not "%%~dpa"=="!oldFolder!" (
echo %%~ta %%~fa
set "oldFolder=%%~dpa"
)
del /q "%tempFile%" >nul 2>nul
Option 1 will recurse over the folders structure and for each one, a dir command is executed to retrieve the list of files in the folder in descending date order. The first in the list is the most rececent one.
Option 2 will use only one dir command to retrieve the full list of files in descending date order and will save the retrieved information in a temporary file. Then the file is processed. Each time the name of the folder changes, output the first line that will be the most recent file in the folder.
Option 1 will start earlier to echo information, but as multiple commands are used, it will require more time to execute, but needs less memory as it will only retrieve the file list of one folder each time.
Option 2 uses less commands and will be faster, but uses a temporary file and requires more memory that Option 1 as the full file list will be loaded in memory.
Select depending of how deep is your folder structure, how much files you have, how much memory, .... just test.

Resources