【问题标题】:Batch Script to Organize Files by Date按日期组织文件的批处理脚本
【发布时间】:2015-12-28 23:52:34
【问题描述】:

我正在尝试将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 在某些文件上是空白的。在完成移动文件部分之前,我想弄清楚这个问题。

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

【问题讨论】:

  • 尝试将/a 开关用于一年的set
  • @ClaytonWahlstrom 这似乎只是将输出的“~6,4”更改为“-7”。
  • 你做了set /a year=!FileDate:~6,4!吗?
  • 首先将FOR %%a in (%%i) do set FileDate=%%~ta换成set FileDate=%%~ti;然后删除@echo off 并尝试捕获FileDate 为空的项目...
  • @aschipfl 谢谢这似乎有效!我从其他地方得到那条线,我不确定他们为什么使用循环......有人也可以帮助复制部分吗?我认为xcopy 是一个不错的选择,但我似乎无法让变量路径正常工作。我试着做set filepath=!i:~2,999! 然后xcopy "!filepath!" "T:\Pre2010\!filepath!",但我的文件路径变量有问题。我只需要从当前文件的路径中删除第一个字符T:

标签: windows batch-file windows-7 scripting


【解决方案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 日期之前/之后有可见日期中断的文件。

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

【讨论】:

    【解决方案2】:

    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 枚举的目录树。根据this postfor /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 /R 替换为for /Fdir /B /S,这就是我所做的:

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

    【讨论】:

    • 非常感谢您的帮助!这是一个很好的答案,但为了简单起见,我想我会坚持使用 robocopy。我很感激你和我一起工作。再次感谢!
    【解决方案3】:

    感谢我收到的两个答案的帮助!他们都帮助我找到了最终的解决方案。为了简单起见,我决定使用 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
    

    【讨论】:

      猜你喜欢
      • 2015-02-28
      • 1970-01-01
      • 2014-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-03
      • 2018-07-02
      相关资源
      最近更新 更多