复制子目录,保留较大的文件

时间:2013-09-20 16:31:56

标签: windows batch-file cmd compare

我试图在Windows 7计算机上组合两个目录,这些目录具有一些相同的子文件夹(但不是全部)和一些相同的文件(但不是全部)。我想复制

例如,我有以下目录结构,想要组合(复制或移动)" Dir_A"和" Dir_Z"。如果文件存在于目标目录中,我想比较文件大小并保留两个文件中较大的文件。

Dir A
    Dir B
        file 1.txt
        file 2.txt
        file 3.txt
    Dir C
        file 4.txt
    Dir D
        file 5.txt
        file 6.txt
Dir_Z
    Dir Y
        file 8.txt
    Dir C
        file 4.txt
    Dir D
        file 6.txt

我很舒服使用cmd文件或PowerShell。先感谢您。

编辑:修改以在导演和文件名中包含空格并添加到目前为止的内容。

这是我到目前为止所做的事情。它似乎适用于目录或文件名中有空格的情况。

@echo off
echo :: Combine two folders, Keep the larger of any given files, Delete the other

if "%1"=="" goto :NoParam
if "%2"=="" goto :NoParam
setlocal enabledelayedexpansion
set SOURCE_DIR=%1
set DEST_DIR=%2

for /R "%SOURCE_DIR%" %%S in (*) do (
echo Source: "%%S"
@echo off

for /f "delims=" %%R in ('call MakeRelative.cmd "%%S" "%SOURCE_DIR%"') do ( 
set FILE_REL="%%R"

set filename=%DEST_DIR%\%%R
For %%D in ("!filename!") do (
Set Name=%%~nxD

if exist %DEST_DIR%\%%R (
    echo File Exists
if %%~zD lss %%~zS (
    echo Destination %%~zD is smaller than Source %%~zS
    call robocopy %%~dpS %%~dpD "!Name!" /MOV
) else  del %%S && Echo File is not larger, Deleting %%S

) else call robocopy %%~dpS %%~dpD "!Name!" /MOV
)
)
)

Pause
goto :eof

:NoParam
echo.
echo Syntax: %0 [Source_DIR] [Dest_DIR]
goto :eof

我使用了MakeRelative.cmd,如下所示:http://www.dostips.com/DtCodeCmdLib.php#MakeRelative

我很抱歉这不优雅。

1 个答案:

答案 0 :(得分:0)

我不是一个PowerShell开发人员,但是这应该做的工作,并且希望它比批处理文件更明显。

if($args.length -ne 3) {
    "usage: PowerShell ThisScriptName.ps1 -command ""SourceDirectory"" ""DestinationDirectory""";
    Exit
}

function CopyFileIfSourceIsLarger($SourceFile, $DestinationFile) {
    $S = New-Object IO.FileInfo($SourceFile.ToString());
    $D = New-Object IO.FileInfo($DestinationFile.ToString());
    if ($S.Length -gt $D.Length ) {
        "Overwriting smaller file " + $D.FullName;
        [IO.File]::Copy($S.FullName, $D.FullName, $true);
    }
}

$SourceDir = New-Object IO.DirectoryInfo($args[1]);
$DestinationDir = New-Object IO.DirectoryInfo($args[2]);
$SourceDirectoryPath = $SourceDir.FullName;
$DestinationDirectoryPath = $DestinationDir.FullName;

"Source Path: " + $SourceDirectoryPath;
"Destination Path: " + $DestinationDirectoryPath;

$SourceItems = Get-ChildItem -recurse $SourceDir;

"Synchronizing Directory Structure..."
foreach ($dir in $SourceItems | ? { $_ -is [IO.DirectoryInfo] })  {
  $sourceRelative = $dir.fullname.Substring($SourceDirectoryPath.length + 1);
  if ([IO.Directory]::Exists([IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative)) -eq $false) {
    "Creating folder " + [IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative);
    [IO.Directory]::CreateDirectory([IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative)) | out-null;
  }
}

"Synchronizing Files..."
foreach ($file in $SourceItems | ? { $_ -is [IO.FileInfo] })  {
    $sourceRelative = $file.fullname.Substring($SourceDirectoryPath.length + 1);
    if ([IO.File]::Exists([IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative)) -eq $true) {
        CopyFileIfSourceIsLarger ([IO.Path]::Combine($SourceDirectoryPath,$sourceRelative).ToString()) ([IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative).ToString());
    } else {
        "Creating file " + [IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative);
        [IO.File]::Copy([IO.Path]::Combine($SourceDirectoryPath,$sourceRelative).ToString(),[IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative).ToString()) | out-null;
    }
}

"All done."

#Thanks to:
#"Identifying Object Types": http://powershell.com/cs/blogs/tobias/archive/2008/10/14/identifying-object-types.aspx
#"Exiting early from foreach": http://stackoverflow.com/questions/10277994/powershell-how-to-exit-from-foreach-object
#"Calling functions with multiple parameters" http://stackoverflow.com/questions/4988226/powershell-multiple-function-parameters

当脚本运行时,文件1,2,3,5,9和10会被复制,文件6会被覆盖,因为它在目标中较小。

这是一个批处理文件,用于设置测试用例(以及一些额外的文件夹来测试名称中的空格)。为了安全起见,我已经注释掉清除目录A和Z的两行,但是如果你不关心删除当前目录中文件夹A和Z中的文件,你可以删除REM语句。

@ECHO OFF

REM Uncomment at own risk RD /S /Q A
REM Uncomment at own risk RD /S /Q Z

MD "A\B"
echo aaaaaaaabbbbbbbbcccccccc>"A\B\file 1.txt"
echo aaaaaaaabbbbbbbbcccccccc>"A\B\file 2.txt"
echo aaaaaaaabbbbbbbbcccccccc>"A\B\file 3.txt"
MD "A\C"
echo aaaaaaaabbbbbbbbcccccccc>"A\C\file 4.txt"
MD "A\D"
echo aaaaaaaabbbbbbbbcccccccc>"A\D\file 5.txt"
echo aaaaaaaabbbbbbbbcccccccc>"A\D\file 6.txt"
MD "A\FOLDER E"
echo aaaaaaaabbbbbbbbcccccccc>"A\FOLDER E\file 9.txt"
echo aaaaaaaabbbbbbbbcccccccc>"A\FOLDER E\file 10.txt"
MD "Z\Y"
echo aaaaaaaabbbbbbbbcccccccc>"Z\Y\file 8.txt"
MD "Z\C"
echo aaaaaaaabbbbbbbbccccccccdddddddd>"Z\C\file 4.txt"
MD "Z\D"
echo aaaaaaaa>"Z\D\file 6.txt"