I am trying to organize all files (and directories) on the T:
drive into two directories: Pre2010
and PostAnd2010
. The files should be organized based on their last modified time--so if file T:\\dirA\\fileA1
has the timestamp 12/28/2015 03:42pm
it should be moved to T:\\PostAnd2010\\dirA\\
, maintaining the same file name. Also, if the file T:\\dirA\\fileA2
has the timestamp 1/13/2009 12:23am
it should be moved to T:\\Pre2010\\dirA\\
with the same filename. So the new Pre2010
and PostAnd2010
directories should maintain the same directory structure as the T:
drive previously had, but splitting the files by date.
I don't really have any experience writing batch files, but I have been trying! Here's my code so far:
@ECHO OFF
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
chdir /d T:
FOR /r %%i IN (*) do (
FOR %%a in (%%i) do set FileDate=%%~ta
set year=!FileDate:~6,4!
if !year! LSS 2010 (
REM Move to T:\Pre2010\<filepath>
echo !year! is before 2010
) else (
REM Move to T:\PostAnd2010\<filepath>
echo !year! is 2010 or after
)
REM echo !year!
pause
)
echo Done.
pause
This seemed to be working okay, but then I noticed that the year would occasionally be printed as ~6,4
instead of the actual year. I checked the timestamps of the files that were causing the issue, but nothing seemed strange about them. I am not sure why FileDate
and year
are blank on some files. I want to figure out this issue before I finish the moving the files portion.
Any help would be greatly appreciated! Thanks!
robocopy /?
for help, particularly:
/MAXAGE:n :: MAXimum file AGE - exclude files older than n days/date.
/MINAGE:n :: MINimum file AGE - exclude files newer than n days/date.
/MAXLAD:n :: MAXimum Last Access Date - exclude files unused since n.
/MINLAD:n :: MINimum Last Access Date - exclude files used since n.
(If n < 1900 then n = n days, else n = YYYYMMDD date).
Use /L
to see what robocopy will do.
Use /MIR
to do the actual move.
rem /L to see what it does
robocopy l:\test\fileage\all l:\test\fileage\old /MINAGE:20151002 /L /MIR
or
rem /MIR to actually move the files
robocopy l:\test\fileage\all l:\test\fileage\old /MINAGE:20151002 /MIR
rem /L to see what it does
robocopy l:\test\fileage\all l:\test\fileage\new /MAXAGE:20151002 /L /MIR
or
rem /MIR to actually move the files
robocopy l:\test\fileage\all l:\test\fileage\new /MAXAGE:20151002 /MIR
What I did was copy c:\\windows\\system32\\nv*.dll l:\\test\\fileage\\all
This gave me a small list of files that had a visible date break before/after the 20151002 date.
You should be able to adapt easily to your directory names.
Kory Gill's answer leads you to the easiest and most efficient way for your task, using robocopy
:
rem Remove the `/L` switch to actually move items:
robocopy "T:\" "T:\Pre2010" "*.*" /L /E /MOVE /XD "Pre2010" "PostAnd2010" /MINAGE:20100101
robocopy "T:\" "T:\PostAnd2010" "*.*" /L /E /MOVE /XD "Pre2010" "PostAnd2010" /MAXAGE:20100101
However, I want to rely on your code.
You used a for /R
loop iterating through all items in the root of T:
. The destination directories Pre2010
and PostAnd2010
are also located there. Since you are moving files, you are manipulating the directory tree which is enumerated by for /R
. As per this post , for /R
does not enumerate the entire directory tree before iterating, so unexpected results may occur. To overcome this, use the dir /B /S
command and parse its output by a for /F
loop instead, so the entire directory tree is enumerated before the loop actually starts to iterate through all the items. See the following code:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "YEAR=2010"
set "OLDDIR=Pre2010"
set "NEWDIR=PostAnd2010"
chdir /D "T:\"
for /F "eol=| delims=" %%F in ('
dir /S /B /A:-D "*.*"
') do (
set "FILEDATE=%%~tF"
rem The following depends on the region settings:
if "FILEDATE:~6,4!" LSS %YEAR% (
xcopy /L "%%~fF" "%%~dF\%OLDDIR%%%~pF"
) else (
xcopy /L "%%~fF" "%%~dF\%NEWDIR%%%~pF"
)
)
call :CLEANUP
endlocal
exit /B
:CLEANUP
ECHO del /Q "*.*"
for /F "eol=| delims=" %%D in ('
dir /S /B /A:D "*.*"
') do (
set "PATHNAME=%%~fD"
if "!PATHNAME:%OLDDIR%=!"=="!PATHNAME!" (
if "!PATHNAME:%NEWDIR%=!"=="!PATHNAME!" (
ECHO rmdir /S /Q "%%~fD"
)
)
)
exit /B
Besides the replacement of for /R
by for /F
and dir /B /S
, this is what I did:
OLDDIR
, NEWDIR
and YEAR
, resp.; YEAR
and queried FILEDATE:~6,4
immediately; move
by xcopy
, because move
moves files only, so there were only empty directories left finally; so I use xcopy
and delete the source files and directories later; remove the /L
switch from both xcopy
commands to actually copy anything, otherwise it just lists what would be copied; echo
and pause
statements for debuggung; for /F
loop, jump to :CLEANUP
subroutine; :CLEANUP
routine that deletes everything in the source T:\\
except the two destination directories, of course; at first, files in the root dierctory are deleted, then the source directory tree is removed; remove the upper-case ECHO
s (twice) to actually delete any source files and directories, otherwise it just outputs what would be deleted; I appreciate the help from the two answers that I received! They both helped me come to a final solution. I decided to use robocopy instead of the looping I was originally using for simplicity. I ran the script on the drive, which had around 50gb of data and it took a couple hours. I'm slightly concerned by robocopy's output because it reports skipped files and directories; it might be fine though. Here's what I ended up using:
@echo off
chdir /d T:
robocopy T: "T:\Pre2010" /MINAGE:20091231 /S
pause
robocopy T: "T:\PostAnd2010" /MAXAGE:20100101 /S
pause
echo Done!
pause
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.