Windows Shell Command to Show File Name and Last Access Time - windows

I am trying to write a Windows command to list files and their last access times, sorted by access time.
I have used
dir [directory] /O:D /T:A /S /B > output.txt
This outputs the files in directory and sub directories in order by their last access time; however I also need it to output the last access time as well. How is this accomplished?

from within a batch file:
>output.txt (
for /f "delims=" %%F in ('dir /o:d /t:a /s /b "c:\myPath\*"') #echo %%~tF %%F
)
However, there are some things you need to be aware of:
The files are sorted by access timestamp within a directory. It does not sort by access timestamp across all the directories. Your original code has the same problem. To sort accross directories requires parsing the access timestamp and converting it into a string that will sort chronologically when ordered via SORT. Something like "yyyy-mm-dd hh24:mm". Even that is not particularly good because you don't have access to the seconds. You could use WMIC DATAFILE to list file names with last access timestamps at a sub-second level. But why bother, considering that...
The last access timestamp maintained by Windows is not reliable! There are many situations whereby an application can read a file and yet the last access timestamp is not updated. I've seen some reference material somewhere that talks about that, but I don't remember where.
If you still think you want to get a list of files sorted by last access timestamp for an entire folder hierarchy, then the following will work. Assume you want to list all files under "c:\test\"
wmic datafile where "drive='c:' and path like '\\test\\%'" get name, lastaccessed | sort
The timestamp will have the format YYYYMMDDhhmmssddddddZZZZ where
YYYY = year
MM = month
DD = day
hh = hour (24 hour format)
mm = minutes
ss = seconds
dddddd = micro seconds
ZZZZ = timezone, expressed as minutes difference from GMT (the 1st character is the sign)
EDIT
The wildcard search in WMIC causes terrible performance. Here is a version that iterates through all the folders in the root hierarchy, running WMIC against each specific folder (no wildcard). It has decent performance.
#echo off
setlocal disableDelayedExpansion
set "root=c:\test"
set "output=output.txt"
set "tempFile=%temp%\dir_ts_%random%.txt"
(
for /d /r "%root%" %%F in (.) do (
set "folder=%%~pnxF\"
set "drive=%%~dF"
setlocal enableDelayedExpansion
2>nul wmic datafile where "drive='!drive!' and path='!folder:\=\\!'" get name, lastaccessed|findstr /brc:[0-9]
endlocal
)
) >"%tempFile%
sort "%tempFile%" >"%output%"
del "%tempFile%"

Related

Need to view merged photos directory in date sequence

I have two photo folders taken with different cameras, and want to merge them by date, and then view the combined directory in date sequence. I have merged them, and the directory dates look good, but the tools I use insist of showing the photos in name sequence, which is not what I want. I thought of doing a batch rename function to make the date part of the file names, using a bat file, but the DOS DIR command doesn't seem to use this date - if I do
for /f "skip=5 tokens=1,2,4,5* delims= " %%i in ('dir /a:-d /o:d /t:c') do (
etc., most of the file dates are correct, but some of the files seem to be using the "created date" of the directory.
Maybe there is a simple solution as this must be a common problem, but I haven't found a good solution - short of doing a laborious manual rename of some 700+ files!
Help would be appreciated!
Paul M.
for /f "tokens=1*delims=[]" %%a in ('dir /b /a-d /od /t:c^|find /v /n "" ') do echo ren "%%b" "%%a%%~xb"
Perform a directory scan of the source directory, in /b basic mode /a-d without directories in date order selecting created-date, number in brackets each line that doesn't match an empty string and assign each filename found to %%b and the number to %%a
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO REN to REN to actually rename the files.
Note: filenames that begin [ or ] will be processed incorrectly. If an existing file has a name which belongs to the target nameset (ie 1.? 2.? etc.) then simply prefix the target name with a prefix that doesn't already exist, eg ren "%%b" "new_%%a%%~xb" (where there are no existing files named new_*)
I'm not sure about Win7's capability when displaying files using the utility you are using (Explorer?) Win10 has the capability of selecting display by creation-date (select sort by then creation-date)
If you are sure you are sorting by creation-date then probably you'd need to select some other sorting scheme (change t:c to t perhaps)
If there are filenames that aren't being converted, then you are probably adding files (called img*) to a directory that already contains files named 1,2,3... - in fact, it's difficult to see how that phenomenon could happen otherwise.
Change "%%a%%~xb" in the rename command to "xyz%%a%%~xb" and you should find that the files are then all renamed xyz1,xyz2,xyz3 etc. If you then reprocess the files with xyz removed, the names should become 1,2,3 with no omissions.

batch - execute command for every file with specific creation date

got this piece of code:
forfiles /P %ParentFolder% /S /M %Format% /C "cmd /c %exeFile% #path"
executing some exe for every file matching format as parameter.
any way to add "creation date" as a condition to run command via CMD?
something like :
for all files in directory (recursive) X if creation date newer then 1 day ago do (run) some exe with this file's path as param
This is not possible with forfiles, because, when the /D option is provided, it only regards the last modification date only (not even the modification time).
Unfortunately, there are no native commands for date/time maths, so I suggest to switch to a language that is capable of that; for instance, PowerShell, VBScript, JavaScript (which are all native to Windows past XP).
In case the modification date could be used, and a simple check with the date of today is sufficient, the following forfiles command line could be used:
forfiles /S /P "%ParentFolder%" /M "%Format%" /D +0 /C "cmd /C \"%exeFile%\" #path"
The /D option with a non-negative number lets forfiles return files that have been modified the given number of days after today or later (although you would need a time-machine; hence I consider this a design flaw). For +0 as the given number of days, all matching files modified today are returned, because forfiles /D only checks the modification date but does not care about the modification time.
If a simple equality check of the creation date with the date of today is fine for you, it can be done in batch-file scripting quite easily though (see all the explanatory rem remarks for how the following script works):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "ParentFolder=."
set "Format=*.*"
set "exeFile=" & rem // (full path to executable file)
set "tmpFile=%TEMP%\%~n0_%RANDOM%.tmp"
rem // Create a temporary file and retrieve its creation date:
2> nul del "%tmpFile%" & > "%tmpFile%" break & set "TODAY="
for /F "skip=5" %%J in ('dir /N /4 /-C /T:C "%tmpFile%"') do (
if not defined TODAY set "TODAY=%%J" & del "%tmpFile%"
)
rem // Change to predefined parent directory:
pushd "%ParentFolder%" && (
rem // Return all files recursively:
for /F "delims=" %%I in ('dir /B /S /A:-D "%Format%"') do (
rem // Determine the creation date for the current file:
set "FIRST=#"
for /F "skip=5" %%J in ('dir /N /-C /T:C "%%I"') do (
rem // Regard line listing file only, ignore summary lines:
if defined FIRST (
set "FIRST="
rem // Check creation date against today:
if "%%J"=="%TODAY%" (
rem // Return files created today:
echo "%%I" has been created today.
rem // Run external program on found file:
if defined exeFile "%exeFile%" "%%I"
)
)
)
)
rem // Restore previous working directory:
popd
)
endlocal
exit /B
I am using two dir command lines here:
the first one returns a bare list of files recursively (/S; no directories because of /A:-D) without any dates/times, headers and footers, due to switch /B; not using this switch would lead to header and footer lines for the whole output and for every iterated sub-directory also, so the output would be quite complicated to be parsed;
the second one receives each file returned by the first one; since there is no /B but the /N option, the file creation date/time is returned (/T:C); for every file the output looks like this:
Volume in drive D is DATA
Volume Serial Number is 0000-0000
Directory of D:\Data
2016/09/29 16:00 1024 current_file.txt
1 File(s) 1024 bytes
0 Dir(s) 1099511623680 bytes free
the first token of the sixth line constituting the creation date is split off and compared against the current date %DATE%; to ignore the header, the skip=5 option of the for /F loop is used; to ignore the summary lines, the variable FIRST is used;
Note that the date format is locale-dependent; as long as there appear no spaces in the date, this is no problem as the current date is also determined by the dir command applied on a temporary file.
Looking at the forfiles /? shows the switch /D that will exclude files that are younger (/d -<days>) or older (/d +<days>) than the given value for <days>.
As you want the files from today, you would set <date> to 0.
Notice, that this will look on the changed date!
Other way would be to use a for /r-loop and get a list of the creation date with dir /T:C ; to sort it add /O-D. Then separate that using a for /f loop to get the lines of the output of dir and another one to separate it (possibly easier without the nested loops).
You can than compare the creation date with %date% or when using one day=24 hrs compare the creation time with %time% additionally.

Windows batch file renaming via reordering/manipulating current name

I have a large amount of files in multiple folders, the file name format is:
FILE DESCRIPTION_MM DD YYYY_F_XXXXX.EXTENSION
The FILE DESCRIPTION is a variable amount of characters. XXXXX is a variable amount of characters as well. The extension is either pdf, doc or docx. The delimiter to be used is the first instance of _. Example:
Foo File_01 01 2016_F_Bar.pdf
I need to rename each file by reordering the Date to the front. Instead of the current format, it needs to be
MM DD YYYY_FILE DESCRIPTION_F_XXXXX.EXTENSION".
Thus I need to cut out DATE and the 2nd instance of _ and move it to the front of the filename. This amounts to 11 characters in total including the _.
The extension needs to be unchanged. Using the above example:
01 01 2016_Foo File_01 01 2016_F_Bar.pdf
Also I only want to rename the files in the format "FILE DESCRIPTION_MM DD YYYY_F_XXXXX.EXTENSION" ignoring all other cases in which files are already formatted with the DATE in the front and cases where there is no DATE.
Any help would be greatly appreciated!
Give this a try on some test data
#echo off
FOR /F "delims=" %%G IN ('dir /a-d /b /s *_*_*.pdf *_*_*.doc *_*_*.docx ^|findstr /R /C:".*_[0-9][0-9] [0-9][0-9] [0-9][0-9][0-9][0-9]_F_.*\."') DO (
FOR /F "TOKENS=1,2* delims=_" %%H IN ("%%~nxG") DO rename "%%~G" "%%~I_%%~H_%%~J"
)

comparing file size and modified date

I am trying to build a batch script to confirm both file size and modified date. as of i have been using different commands (diff, comp, and others) that are not giving me the needed outcome. both files are found remotely and are in different time zones so using a dir command output didnt work for me.
ask for computer name or keywork to pull list from a txt file
set /P "ComputerName=Please enter the computer name or the word batch to pull from computernames.txt: "
compare two locations
file1= (fixed server location)\file.zip(or txt)
file2= \\%ComputerName%\m$\file.zip(or txt)
compare date modified (this file is modified once a week but can not use time stamp since the file goes out to computers in different time zones and if the copy has an issue it reverts back to last successful file date or "beginning of time" time stamp)
compare size (files that fail a copy with default to a 0 size or size where it got stuck)
if file1 = file2
end or proceed to next file in batch
if file1 does not equal file 2 (both conditions)
export %ComputerName% name to file
once confirmed end or continue next in txt list
Not really sure this will work in your environment, but... while FAT partitions use the local time to save file timestamps, NTFS use UTC time. And this timestamp can be retrieved using robocopy
#echo off
setlocal enableextensions disabledelayedexpansion
call :getFileData "%cd%\file1.zip" file1
call :getFileData "%cd%\file2.zip" file2
echo file1 : %file1%
echo file2 : %file2%
if "%file1%"=="%file2%" (
echo Both files has the same size/timestamp
) else (
echo Files has different size/timestamp
)
goto :eof
:getFileData file returnVar
rem Prepare environment
setlocal enableextensions disabledelayedexpansion
set "fileData="
rem Retrieve file size and time stamp
for /f "tokens=1-3" %%a in ('
robocopy "%~dp1\." "%~dp1\." "%~nx1" /l /is /ts /nc /ndl /njh /njs 2^>nul
') do set "fileData=%%a %%b %%c"
rem Handle non existing files
if not defined fileData set "fileData=FileNotFound %random%%random%%random%"
rem Return or show data
endlocal & if "%~2"=="" (echo(%fileData%) else (set "%~2=%fileData%")
exit /b

Renaming a batch file and keeping part of the filename

I've seen plenty of posts on similar requests but I can't quite find one that suits what I am trying to do. It is fairly simple but I cannot seem to get it.
ren FILE??.txt FILE%Year%%Month%%Day%??.txt
copy FILE%Year%%Month%%Day%??.txt C:\Users\me\Desktop\Batch\renamed\achod%Year%%Month%%Day%??.txt
I cannot get the script to keep the '??' which represents random characters the first file may have.
Any help is appreciated.
You won't be able to rename files directly using a wildcard character. Instead you need to locate all the applicable files and then rename each.
The script below works under the assumptions of your question/comments:
File name is 6 chars long.
Only the last 2 chars are interchangeable.
Of course, the script could be very easily adapted to accomodate other settings but this does just as you requested.
SETLOCAL EnableDelayedExpansion
REM Set your Year, Month, Day variable values here.
REM They will be used for file renaming.
...
CD "C:\Path\To\Files"
FOR /F "usebackq tokens=* delims=" %%A IN (`DIR "File??.txt" /B /A:-D`) DO (
REM Extract the last 2 chars of the file name.
SET FileName=%%~nA
SET First4=!FileName:~0,4!
SET Last2=!FileName:~-2!
REM Rename the file, inserting the new data.
RENAME "%%A" "!First4!%Year%%Month%%Day%!Last2!%%~xA"
)
ENDLOCAL

Resources