使用最新文件

时间:2017-07-28 12:08:06

标签: windows synchronization backup

我有大约12TB(并且正在增长)的库,分布在3个硬盘驱动器上的视频文件,我想将它们备份到外部硬盘。我使用的是Windows 10 Pro。

我的备份驱动器只有8TB,我想始终备份最新的8TB视频文件。到目前为止,我已经尝试了大约10个同步工具,但没有一个允许我根据创建日期复制文件。

另外,对于robocopy,我还没有办法只复制最新的8TB文件。
有什么建议?

1 个答案:

答案 0 :(得分:0)

我有2个批处理脚本,可以满足您的要求。它们之间的主要区别在于,第一个脚本使用where来查找将使用上次更改的时间戳的所有文件。要使用其他时间戳,例如最后一次访问或创建时间您必须使用我附加的第二个使用dir的脚本。

<强> 1。 使用where批处理脚本来查找文件:

至少需要2个参数:
用法:batch.bat <dst> <src_1> [<src_...> <src_n>]

它使用where /r <src_n> * /t命令,该命令将构建所有子目录中所有文件的列表,其中包含以下格式的最后一次更改的时间戳:

<size>   <date>          <time>    <file name>
  5397   11.07.2017      14:32:09  C:\Users\...\foo.txt
 10860   12.07.2017      11:25:15  C:\Users\...\bar.log

如果您需要创建时间或上次访问,时间戳是最后一次更改,请使用dir下面的第二个批处理脚本,因为可以在不同的时间戳之间进行选择。

对于通过参数列表传递的每个源,此输出将被写入(不包含列size)到temp dir %TEMP%下的临时文件(将在脚本后自动删除)。完整的临时文件按日期和时间排序,最新的。

此分类输出将用于将其复制到目标文件夹中。

示例:

cmd中的当前目录为C:\...\Desktop):
batch.bat "backup_folder" "F:\folder" "F:\folder with space"

当前目录:
batch.bat "C:\...\Desktop\backup_folder" "F:\folder" "F:\folder with space"

C:\...\Desktop\backup_folder将包含2个文件夹folderfolder with space,其中包含脚本操作后这些源文件夹的所有文件。

在您的情况下,批处理脚本只会复制8 TB的最新文件,因为驱动程序已满,批处理脚本将退出,因为它识别出复制错误。

批处理脚本:

@echo off
setlocal enabledelayedexpansion

rem Check if at least 2 arguments are passed
set INVARGS=0
if [%1] == [] set INVARGS=1
if [%2] == [] set INVARGS=1
if %INVARGS% == 1 (
   echo Usage: %0 ^<dst^> ^<src_1^> ^<src_...^> ^<src_n^>
   goto :EOF
)

rem Store Carriage return character in CR (used for spinner function, see below)
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

rem Set temp file name
set "uniqueFile=%TEMP%\%0_%RANDOM%.tmp"

rem Set destination path and shift to next argument
set "dstpath=%~1"
shift

rem Store src_1 to src_n arguments into src array
set idx=0
:again
rem If %1 is blank, we are finished
if not [%1] == [] (
   if not exist "%~1" (
      echo The following source folder doesn't exist:
      echo    "%~1"!
      echo The program will terminate!
      goto :end
   )

   pushd "%~1"
   set "src[%idx%]=!cd!"
   if [!src[%idx%]:~-1!] == [\] (
      set src[%idx%]=!src[%idx%]:~0,-1!
   )
   set /a idx=%idx%+1
   popd

   rem Shift the arguments and examine %1 again
   shift

   goto :again
)

rem Build command string:
rem where /r "src_1" * /t ^& where /r "src_..." * /t ^& where /r "src_n" * /t ^& break"
set "command="
for /F "tokens=2 delims==" %%s in ('set src[') do (
   set "command=!command!where /r "%%s" * /t ^& "
)
set "command=!command!break"

echo "Command: ^<!command!^>"

rem Clear temp file and write files to copy in it
break>"%uniqueFile%"
for /f "tokens=2,3,4,* delims= " %%F in ('!command!') do (
   call :spinner
   echo %%F %%G %%H %%I>>"%uniqueFile%"
)

rem Open the built file list
echo File list will be opened...
%uniqueFile%
rem Ask user if copying should start
echo Should this files copied into %dstpath%? (Y/N)
set INPUT=
set /P INPUT=Answer?:%=%
if not [%INPUT%] == [y] (
   if not [%INPUT%] == [Y] (
      goto :end
   )
)

set "dstpathPart="
rem Sort files newest first (last changed timestamp)
for /f "tokens=3,* delims= " %%F in ('type "%uniqueFile%" ^| sort /r') do (
   rem Build destination part from source folder names
   call :buildDestinationPath dstpathPart "%%F %%G"

   rem Prepend the destination folder
   set "dstFile=!dstpath!\!dstpathPart!"

   rem Make directories that doesn't exists
   for %%F in ("!dstFile!") do set "directory=%%~dpF"
   if not exist "!directory!" ( mkdir "!directory!" )

   rem Copy files and echo it
   echo copy /y "!file!" "!dstFile!"
   copy /y "!file!" "!dstFile!"
   echo.

   rem If copying failed exit program
   if errorlevel 1 (
      echo Copying failed... Maybe there is no more space on the disk!
      echo The program will terminate!
      goto :end
   )
)
goto :end


rem Function definitions
:buildDestinationPath
for /F "tokens=2 delims==" %%s in ('set src[') do (
   rem Go into folder e.g.: C:\src_1\ --> C:\
   pushd "%%s"
   cd ..
   rem file contains full path of the where command
   set "file=%~2"

   rem Remove trailing space
   if "!file:~-1!" == " " (
      call set "file=%%file:~0,-1%%"
   )

   rem remove src folder from file to make it relative
   rem e.g. C:\src_1\foo\bar\file1.txt --> src_1\foo\bar\file1.txt
   call set "dstpathPart_temp=%%file:!cd!=%%"

   rem Switch back to origin folder
   popd

   rem If the folder name changed the substring taken was right so take next
   if not [!dstpathPart_temp!] == [!file!] (
      set "%~1=!dstpathPart_temp!"
      goto :next
   )
)
:next
goto :EOF

:spinner
set /a "spinner=(spinner + 1) %% 4"
set "spinChars=\|/-"
<nul set /p ".=Building file list... !spinChars:~%spinner%,1!!CR!"
goto :EOF

:end
del "%uniqueFile%"
goto :EOF

<强> 2。 使用dir批处理脚本来查找文件:

需要多一个参数,以便您至少需要3个参数:
用法:batch.bat <timeordering> <dst> <src_1> [<src_...> <src_n>]

它将生成与上述相同的列表,但借助dir命令。 dir命令采用以下参数,即脚本的<timeordering>参数:

/tc Creation
/ta Last access
/tw Last written

批处理脚本:

@echo off
setlocal enabledelayedexpansion

rem Check if at least 2 arguments are passed
set INVARGS=0
if [%1] == [] set INVARGS=1
if [%2] == [] set INVARGS=1
if [%3] == [] set INVARGS=1
if %INVARGS% == 1 (
   echo Usage: %0 ^<timeordering^> ^<dst^> ^<src_1^> ^<src_...^> ^<src_n^>
   goto :EOF
)

rem Store Carriage return character in CR (used for spinner function, see below)
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

rem Set temp file name
set "uniqueFile=%TEMP%\%0_%RANDOM%.tmp"

rem Set timeordering and destination path and shift to next argument
set "timeordering=%~1"
shift
set "dstpath=%~1"
shift

rem Store src_1 to src_n arguments into src array
set idx=0
:again
rem If %1 is blank, we are finished
if not [%1] == [] (
   if not exist "%~1" (
      echo The following source folder doesn't exist:
      echo    "%~1"!
      echo The program will terminate!
      goto :end
   )

   pushd "%~1"
   set "src[%idx%]=!cd!"
   if [!src[%idx%]:~-1!] == [\] (
      set src[%idx%]=!src[%idx%]:~0,-1!
   )
   set /a idx=%idx%+1
   popd

   rem Shift the arguments and examine %1 again
   shift

   goto :again
)


rem Clear temp file and write files to copy in it
break>"%uniqueFile%"
rem call commands with all sources:
rem call :getFileInformation /TC "src_1\*"
rem                          /TW
rem                          /TA
for /F "tokens=2 delims==" %%s in ('set src[') do (
   call :getFileInformation %timeordering% "%%s\*" "%uniqueFile%""
)

rem Open the built file list
echo Unsorted file list will be opened...
%uniqueFile%
rem Ask user if copying should start
echo Should this files copied into %dstpath%? (Y/N)
set INPUT=
set /P INPUT=Answer?:%=%
if not [%INPUT%] == [y] (
   if not [%INPUT%] == [Y] (
      goto :end
   )
)

set "dstpathPart="
rem Sort files newest first (last changed timestamp)
for /f "tokens=3,* delims= " %%F in ('type "%uniqueFile%" ^| sort /r') do (
   rem Build destination part from source folder names
   call :buildDestinationPath dstpathPart "%%F %%G"

   rem Prepend the destination folder
   set "dstFile=!dstpath!\!dstpathPart!"

   rem Make directories that doesn't exists
   for %%F in ("!dstFile!") do set "directory=%%~dpF"
   if not exist "!directory!" ( mkdir "!directory!" )

   rem Copy files and echo it
   echo copy /y "!file!" "!dstFile!"
   copy /y "!file!" "!dstFile!"
   echo.

   rem If copying failed exit program
   if errorlevel 1 (
      echo Copying failed... Maybe there is no more space on the disk!
      echo The program will terminate!
      goto :end
   )
)
goto :end


rem Function definitions
:buildDestinationPath
for /F "tokens=2 delims==" %%s in ('set src[') do (
   rem Go into folder e.g.: C:\src_1\ --> C:\
   pushd "%%s"
   cd ..
   rem file contains full path of the where command
   set "file=%~2"

   rem Remove trailing space
   if "!file:~-1!" == " " (
      call set "file=%%file:~0,-1%%"
   )

   rem remove src folder from file to make it relative
   rem e.g. C:\src_1\foo\bar\file1.txt --> src_1\foo\bar\file1.txt
   call set "dstpathPart_temp=%%file:!cd!=%%"

   rem Switch back to origin folder
   popd

   rem If the folder name changed the substring taken was right so take next
   if not [!dstpathPart_temp!] == [!file!] (
      set "%~1=!dstpathPart_temp!"
      goto :next
   )
)
:next
goto :EOF

:getFileInformation
for /f "delims=" %%a in ('dir /s /b /a-d %~1 "%~2"') do (
   for /f "tokens=1,2 delims= " %%b in ('dir %~1 "%%a" ^| findstr /l /c:"%%~nxa"') do (
      echo %%b %%c %%a>>"%~3"
      call :spinner
   )
)
goto :EOF

:spinner
set /a "spinner=(spinner + 1) %% 4"
set "spinChars=\|/-"
<nul set /p ".=Building file list... !spinChars:~%spinner%,1!!CR!"
goto :EOF

:end
del "%uniqueFile%"
goto :EOF