按日期组织文件的批处理脚本

时间:2015-12-28 23:52:34

标签: windows batch-file windows-7 scripting

我正在尝试将T:驱动器上的所有文件(和目录)组织到两个目录中:Pre2010PostAnd2010。应根据文件的上次修改时间对文件进行组织 - 因此,如果文件T:\dirA\fileA1具有时间戳12/28/2015 03:42pm,则应将其移至T:\PostAnd2010\dirA\,并保留相同的文件名。此外,如果文件T:\dirA\fileA2具有时间戳1/13/2009 12:23am,则应将其移至T:\Pre2010\dirA\,并使用相同的文件名。因此,新的Pre2010PostAnd2010目录应保持与先前T:驱动器相同的目录结构,但按日期拆分文件。

我没有任何编写批处理文件的经验,但我一直在努力!到目前为止,这是我的代码:

@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

这似乎工作正常,但后来我注意到,有时会将这一年打印为~6,4而不是实际年份。我检查了导致问题的文件的时间戳,但对他们来说似乎并不奇怪。我不确定为什么FileDateyear在某些文件中是空白的。我想在完成移动文件部分之前弄清楚这个问题。

任何帮助将不胜感激!谢谢!

3 个答案:

答案 0 :(得分:1)

使用ROBOCOPY

robocopy /?寻求帮助,尤其是:

/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).

使用/L查看robocopy会做什么。

使用/MIR进行实际移动。

复制旧文件

rem /L to see what it does
robocopy l:\test\fileage\all l:\test\fileage\old /MINAGE:20151002 /L /MIR

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

rem /MIR to actually move the files
robocopy l:\test\fileage\all l:\test\fileage\new /MAXAGE:20151002 /MIR

创建测试文件......

我做的是copy c:\windows\system32\nv*.dll l:\test\fileage\all

这给了我一个小文件列表,这些文件在20151002日期之前/之后有可见的日期中断。

您应该能够轻松适应您的目录名称。

答案 1 :(得分:1)

Kory Gill's answer使用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

但是,我想依靠你的代码。

您使用for /R循环遍历T:根目录中的所有项目。目标目录Pre2010PostAnd2010也位于此处。由于您正在移动文件,因此您正在操作由for /R枚举的目录树。根据{{​​3}},for /R在迭代之前枚举整个目录树,因此可能会出现意外结果。要解决此问题,请使用dir /B /S命令并通过for /F循环解析其输出,以便在循环实际开始迭代所有循环之前枚举整个目录树项目。请参阅以下代码:

@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

除了for /Rfor /F替换dir /B /S之外,这就是我所做的:

  • 将两个目标目录和年份放入变量OLDDIRNEWDIRYEAR,分别为
  • 删除了临时变量YEAR并立即查询FILEDATE:~6,4;
  • move替换为xcopy,因为move仅移动文件,因此最后只剩下空目录;所以我使用xcopy并稍后删除源文件和目录; 从两个/L命令中移除xcopy开关以实际复制任何内容,否则它只会列出要复制的内容;
  • 删除了debuggung;
  • 的一些echopause语句
  • for /F循环之后,跳转到:CLEANUP子程序;
  • 引入了一个:CLEANUP例程,当然除了两个目标目录之外,它会删除源T:\中的所有内容。首先,删除根目录中的文件,然后删除源目录树; 删除大写ECHO (两次)以实际删除任何源文件和目录,否则只输出要删除的内容;

答案 2 :(得分:0)

我很感谢收到的两个答案的帮助!他们都帮助我找到了最终解决方案。为了简单起见,我决定使用robocopy而不是我最初使用的循环。我在驱动器上运行了脚本,它有大约50GB的数据,花了几个小时。我有点担心robocopy的输出,因为它报告跳过的文件和目录;它可能没问题。这是我最终使用的内容:

@echo off

chdir /d T:

robocopy T: "T:\Pre2010" /MINAGE:20091231 /S
pause

robocopy T: "T:\PostAnd2010" /MAXAGE:20100101 /S
pause

echo Done!
pause