BATCH递归地比较两个文件夹

时间:2016-02-26 13:25:24

标签: windows batch-file

我正在更新一个大的保存脚本,我需要递归地比较2个文件夹。我觉得我很接近,但无法理解缺少的东西......

代码如下:

set Rep1=f:\album1
set Rep2=f:\album2
set logfile=f:\logfile.txt
for /r "%Rep1%\" %%i in (*) do (
    fc "%%i" "%Rep2%\%%~nxi"
    iF ERRORLEVEL == 1 echo "%%i" et "%Rep2%\%%~nxi" Sont differents  >>  %logfile%
    iF ERRORLEVEL == 2 echo "%%i" et "%Rep2%\%%~nxi" Un des fichier est manquant >> %logfile%
)
pause

问题在于它会将f:\album1\folder1\file1.txt等所有文件与f:\album2\file1.txt进行比较,因此比较总是错误的...您可以在图片中看到结果: http://i.stack.imgur.com/IQ9qt.png

如果您有任何人找到解决方案,非常感谢您!

Vincs

2 个答案:

答案 0 :(得分:2)

@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "targetdir=U:\destdir"
FOR /f "delims=" %%a IN (
 'dir /s /b /a-d "%sourcedir%\*" '
 ) DO (
  SET "foundfile="
  FOR /f "delims=" %%c IN (
   'dir /s /b /a-d "%targetdir%\%%~nxa" 2^>nul'
  ) DO (
   SET foundfile=Y
   FC /b "%%a" "%%c" >NUL
   IF ERRORLEVEL 1 ECHO different "%%a" "%%c"
 )
 IF NOT DEFINED foundfile ECHO missing   "%%a" from "%targetdir%"
)
FOR /f "delims=" %%a IN (
 'dir /s /b /a-d "%targetdir%\*" '
 ) DO (
  SET "foundfile="
  FOR /f "delims=" %%c IN (
   'dir /s /b /a-d "%sourcedir%\%%~nxa" 2^>nul'
  ) DO (
   SET foundfile=Y
 )
 IF NOT DEFINED foundfile ECHO missing   "%%a" from "%sourcedir%"
)

GOTO :EOF

您需要更改sourcedirtargetdir的设置以适合您的具体情况。

您的方法存在的一个问题是文件%%i与"%Rep2%\ %% ~nxi"这意味着仅在%rep2%中,而不是在子目录中。

另一个问题是

IF ERRORLEVEL == 1 echo "%%i" et "%Rep2%\%%~nxi" Sont differents  >>  %logfile%

将文字字符串ERRORLEVEL与文字字符串1进行比较,因此找不到匹配项。要使用您的方法,您必须使用delayedexpansion语句启用setlocal enabledelayedexpansion,然后使用IF !ERRORLEVEL!==1 ...

上面发布的解决方案会比较在树上找到的具有相同名称和扩展名的文件,因此如果file1.txt在第一个树中任何地方,那么它将进行比较所有在第二个树中找到 file1.txt个文件。

另请注意,在处理标准系统时会出现标准异常,该系统会为文件提供长名称和短名称。每个文件可能有两个名称 - 而 名称上的dir匹配。

答案 1 :(得分:0)

Magoo's answer已经指出了代码的主要问题。

但是,他提供的解决方案仅使用文件名来查找要比较的文件,因此如果名称相同的文件出现在源目录和目标目录中的不同位置,或者如果在其中出现多个具有相同名称的文件,则它将失败任何目录树。

这是一个类似的解决方案,基于dir /S命令,它还要求树中的每个文件名都是唯一的,并且发生在源和目标内的相同位置(它不检查存在的文件)只在源树或目标树中的一个):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Provide source and target directory paths here:
set "SOURCE=.\source"
set "TARGET=.\target"

rem Convert relative paths to absolute ones:
for %%D in ("%SOURCE%") do set "SOURCE=%%~fD"
for %%D in ("%TARGET%") do set "TARGET=%%~fD"

for /F "eol=| delims=" %%I in ('
    2^> nul dir /B /S /A:-D "%SOURCE%\*.*"
') do (
    set "SRC=%%~fI"
    for /F "eol=| delims=" %%J in ('
        2^> nul dir /B /S /A:-D "%TARGET%\%%~nxI"
    ') do (
        set "TRG=%%~fJ"
        setlocal EnableDelayedExpansion
        > nul fc /B "!SRC!" "!TRG!" || echo "!SRC!" and "!TRG!" differ.
        endlocal
    )
)

endlocal
exit /B

此代码段仅比较源目标树和目标目录树中出现的文件。如果相应的文件不同,则返回相关的消息。

要解决在不同位置使用相同文件名的问题,让我们使用xcopy /L命令,因为它能够返回相对于源目录的路径列表(/L选项可以防止xcopy复制任何文件;附加的find命令会过滤掉? File(s)摘要行:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Provide source and target directory paths here:
set "SOURCE=.\source"
set "TARGET=.\target"

rem Convert relative paths to absolute ones:
for %%D in ("%SOURCE%") do set "SOURCE=%%~fD"
for %%D in ("%TARGET%") do set "TARGET=%%~fD"

pushd "%SOURCE%"
for /F "eol=| delims=" %%I in ('
    2^> nul xcopy /L /S /Y ".\*.*" "%TEMP%\" ^| find ".\"
') do (
    set "SRC=%%~fI"
    pushd "%TARGET%"
    for /F "eol=| delims=" %%J in ('
        2^> nul xcopy /L /Y "%%~I" "%TEMP%\" ^| find ".\"
    ') do (
        set "TRG=%%~fJ"
        setlocal EnableDelayedExpansion
        > nul fc /B "!SRC!" "!TRG!" || echo "!SRC!" and "!TRG!" differ.
        endlocal
    )
    popd
)
popd

endlocal
exit /B

此代码段还仅比较源目标树和目标目录树中出现的文件。如果您还想检查源树和目标树中是否存在每个fils,请查看Magoo's answer,它可以很好地了解如何实现(双循环方法)。