append file date to file name using cmd - windows

Hi I'd like to create a bat file to rename files using the cmd. Say a friend and I went on vacation together. We have put all our pictures together and I now want to rename all the pictures in a sequence.
Say I selected the following pictures:
mypicture_3435.jpg (file date = 01 Jan 2015 10:00)
mypicture_3465.jpg (file date = 04 Jan 2015 12:00)
myfriendspicture_2221.jpg (file date = 03 Jan 2015 12:00)
myfriendspicture_2226.jpg (file date = 04 Jan 2015 11:00)
I would like to get the following output:
ourvacation_01.jpg [mypicture_3435.jpg (file date = 01 Jan 2015
10:00)]
ourvacation_02.jpg [myfriendspicture_2221.jpg (file date = 03
Jan 2015 12:00)]
ourvacation_03.jpg [myfriendspicture_2226.jpg (file
date = 04 Jan 2015 11:00)]
ourvacation_04.jpg [mypicture_3465.jpg
(file date = 04 Jan 2015 12:00)]
This is easy to do with specific software such as acdsee or even with Windows' image browser. But I would like to do it using the command promt. (I teach mathematics in a school and I would like to use this as a programming example).
I tried the follwing script and it worked:
#echo off
setlocal EnableDelayedExpansion
set i=0
for %%a in (*.jpg) do (
set /a i+=1
ren "%%a" "!i!.new"
)
ren *.new *.jpg
But it renamed the files like this:
myfriendspicture_2221.jpg becomes 1.jpg
myfriendspicture_2226.jpg becomes 2.jpg
mypicture_3435.jpg becomes 3.jpg
mypicture_3465.jpg becomes 4.jpg
So the problems are:
They do not keep a chronological sequence.
If I have say 11 items, and sort them by name, the sequence runs 1, 10, 11, 2, 3, 4...
I tried to run dir /od before I rename, but it didn't work, the sequence runs according to the file name.
All the strings I have found regarding this issue append the current date and time to the file name, but not the file date and time to it's own name.
I couldn't find a way to add a leading 0 or 00 to the sequence so that the file name and chronological order match.
Thank you very much in advance for the help.

I tried to run dir /od before I rename, but it didn't work, the sequence runs according to the file name.
Did you simply run dir /od and then for %%a in (*.jpg)? How did you plan to capture the output of dir /od to make it useful, rather than just dumping it to stdout?
Whenever you want to capture the output of a command, use a for /f loop. You should combine the two commands like this:
for /f "delims=" %%I in ('dir /b /o:d *.jpg') do stuff.
Next issue: zero left padding the file names. Can we assume you won't have more than 10,000 pics from your vacation? Then just prepend four zeros to your generated filename, then use the right-most 4 characters to determine the base name of your pics.
#echo off
setlocal enabledelayedexpansion
set /a seq=10001
for /f "delims=" %%I in ('dir /b /o:d *.jpg') do (
rem :: remove the "echo" when you are ready to rename
echo ren "%%~I" "ourvacation_!seq:~-4!.jpg"
set /a seq += 1
)
The result will look a little something like this:
C:\Users\me\Desktop>test.bat
ren "avatar65929_2.jpg" "ourvacation_0001.jpg"
ren "IMG_20140621_190332.jpg" "ourvacation_0002.jpg"
ren "funny-Finding-Neverland-scene-Explorer.jpg" "ourvacation_0003.jpg"
ren "5DFPwMa.jpg" "ourvacation_0004.jpg"
ren "funny-root-math-equation.jpg" "ourvacation_0005.jpg"
ren "196889_145889312230730_1041953273_n.jpg" "ourvacation_0006.jpg"
ren "0001-cf72d77a-509ac348-b92c-fe8af7d2.jpg" "ourvacation_0007.jpg"
ren "IMG_20141230_191526.jpg" "ourvacation_0008.jpg"
ren "20150120_142150.jpg" "ourvacation_0009.jpg"
ren "20150120_145223.jpg" "ourvacation_0010.jpg"

Related

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"
)

Windows Shell Command to Show File Name and Last Access Time

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%"

Batch file to move files by date modified

I have written a batch file, which creates empty folders for each date. My next task is to create another batch file, which moves each file in a directory, into the relevant date folder, based on their date modified. I have read numerous forums and articles on how I can achieve this, but with my limited batch file knowledge, I just cannot seem to get it to work. The code I currently have is shown below, though this does not seem to pull in the date modified. Any help is much appreciated!
SET directory="\directory\path\archive"
FOR /f %%a in ('dir /b "%directory%"') do (
SET fdate=%%~Ta
MOVE "%directory%\%%a" "%directory%\%fdate%"
Until you provide more info as to format of dates, I can't give a definitive answer. But I can show you how I would do it on my machine.
I use yyyy-mm-dd format within file and folder names, so December 13, 2011 would be 2011-12-13. My machine uses mm/dd/yyyy format for dates (12/13/2011). So I would need to translate the %%~tF output from 12/13/2011 into 2011-12-13. Note - / cannot be used used in file or folder names.
So this code would do what you want on my machine:
set "source=\directory\path\archive"
set "targetRoot=\directory\path\archive"
for %%F in ("%source%\*") do (
for /f "tokens=1,2,3 delims=/ " %%A in ("%%~tF") do (
move "%%~fF" "%targetRoot%\%%C-%%A-%%B"
)
)
Addendum - Question in comment asks for method to left pad a number with zeros for dir creation. I see two easy choices. (This really should be a different question)
This first method is simple but tedious and not practical as a general solution
for %%A in (01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31) do ...
The second method is a general solution. Since your assignment is within parentheses, you need to use delayed expansion.
setlocal enableDelayedExpansion
for /l %%A in (1 1 31) do (
set "day=0%%A"
set "day=!day:~-2!
...
)
You increase the number of leading zeros by adding more 0 to the front and then increasing the number of characters you preserve in the substring operation.
BUT - why prepopulate the directories? Your strategy will add directory days that don't exist in the calendar, plus you are likely to have many unused folders for which no files were modified on that day. Better to create the folders only as needed. Then the 0 padding is already done for you, and no unneeded folders are created.
set "source=\directory\path\archive"
set "targetRoot=\directory\path\archive"
for %%F in ("%source%\*") do (
for /f "tokens=1,2,3 delims=/ " %%A in ("%%~tF") do (
if not exist "%targetRoot%\%%C\%%A\%%B" mkdir "%targetRoot%\%%C\%%A\%%B"
move "%%~fF" "%targetRoot%\%%C\%%A\%%B"
)
)
My answer is a simple FOR loop who check all files in current directory and take date from eachone file. Create a folder in format yyyy\yyyy-mm and move file into it.
#echo off
rem not %var% but !var! give us access to internal loop variable value with enabledelayedexpansion.
setlocal enabledelayedexpansion
FOR %%V IN (*.*) DO (
SET filedate=%%~tV
rem echo !filedate!
SET fileyear=!filedate:~6,4!
rem echo !fileyear!
SET filemonth=!filedate:~3,2!
rem echo !filemonth!
rem create directory as yyyy\yyyy-MM
mkdir !fileyear!\!fileyear!-!filemonth! 2>nul
echo move %%V !fileyear!\!fileyear!-!filemonth!\
move %%V !fileyear!\!fileyear!-!filemonth!\ >nul
)
TIP: The filemonth and fileyear variable probably should have other numbers to cut proper yyyy/mm for your country/region timestamp.
TIP: This FOR move the script itself to into one of subdirectory, I run it as Windows Shortcut with enter a Location Path - then this script run in proper place.

How to get the Last Modified date of all files in a folder using Batch

Suppose i have a folder which contains 5 files.
I want to run a batch script which outputs all the filenames in the folder along with the last modified dates.
The output has to be written as a text file.
The output should be as follows:
Sample1.xls 4/7/2011
Sample2.xls 3/6/2011
Sample3.xls 5/4/2011
Sample4.xls 2/4/2011
Sample5.xls 6/2/2011
From the commandline:
for /f %a in ('dir /b') do #echo %a %~ta
This outputs:
D:\temp\modtime>dir
Volume in drive D is Data1
Volume Serial Number is 925B-DC37
Directory of D:\temp\modtime
06/28/2012 05:03 PM <DIR> .
06/28/2012 05:03 PM <DIR> ..
06/28/2012 05:02 PM 2 a.txt
06/28/2012 05:03 PM 2 b.txt
2 File(s) 4 bytes
2 Dir(s) 1,485,646,065,664 bytes free
D:\temp\modtime>for /f %a in ('dir /b') do #echo %a %~ta
a.txt 06/28/2012 05:02 PM
b.txt 06/28/2012 05:03 PM
Make the % into %% to put it in a batch file. If you don't need the times, you can post-process to get rid of them.
You should use dir command i think dir . /o-d
have look to this linke MSDOS DirCommand
also you can create a text file and put the command in the file and save it as .bat file
if you read the link you will see there are many option
check this one
dir *.* /o-n-d /b

Resources