比较两个文件夹及其子文件夹批处理文件

问题描述 投票:0回答:4

我有两个文件夹,其中包含所有相同的文件和子文件夹,但每个文件内的内容可能已更改。我想编写一个批处理文件来搜索每个文件并查找任何差异。对于我想做的事情来说,最好的工具是什么?

windows batch-file
4个回答
14
投票

无需批处理文件。单个 FC 命令即可完成您想要的操作:

fc folder1\* folder2\*

如果需要,您可以更具体地指定第一个文件夹中的文件掩码。例如

folder1\*.txt

该命令将报告文件夹 1 中存在但文件夹 2 中缺失的文件。文件夹 2 中的额外文件将被忽略。

FC 命令有许多选项。在命令提示符下输入

HELP FC
FC /?
以获取更多信息。

编辑

扩展解决方案以支持子文件夹有点棘手。使用 FOR /R 可以轻松迭代给定根目录的文件夹层次结构。问题是获取相对路径,以便层次结构可以应用于另一个根。

最简单的解决方案是使用FORFILES,因为它直接支持相对路径。但 FORFILES 很慢:/

此时,批处理文件就有意义了:

@echo off
setlocal
set "folder1=c:\path\To\Folder1\Root"
set "folder2=d:\path\To\Folder2\Root"
set "fileMask=*"

for /f "delims=" %%F in (
  'echo "."^&forfiles /s /p "%folder1%" /m "%fileMask%" /c "cmd /c if @isdir==TRUE echo @relpath"'
) do fc "%folder1%\%%~F\%fileMask%" "%folder2%\%%~F\*"

4
投票

这是完成任务的另一种方法。将变量 Folder1Folder2 设置为要比较的文件夹的完整路径并运行批处理文件。

输出:

Dup – 文件存在于两个文件夹中并且是相同的。

Dif – 文件存在于两个文件夹中,但文件内容不同。

– 文件存在于一个文件夹中,但不存在于另一个文件夹中。

@Echo Off
SetLocal EnableDelayedExpansion

Set "Folder1=%UserProfile%\Desktop\Test Folder1"
Set "Folder2=%UserProfile%\Desktop\Test Folder2"

For /R "%Folder1%" %%x In (*.*) Do (

    Set "FullPath=%%x"
    Set "RelPath=!FullPath:%Folder1%=!"

    If Exist "%Folder2%!RelPath!" (
      >Nul 2>&1 FC /b "%Folder1%!RelPath!" "%Folder2%!RelPath!" && (
       Echo Dup - %%x
      )||(
       Echo Dif - %%x
      )
    ) Else (
      Echo New - %%x
    )
)

For /R "%Folder2%" %%x In (*.*) Do (

    Set "FullPath=%%x"
    Set "RelPath=!FullPath:%Folder2%=!"

    If Not Exist "%Folder1%!RelPath!" (
      Echo New - %%x
    )
)

更新:

在上述版本中,当文件路径包含感叹号(!)时,将报告为New。这是由于启用了延迟扩展。您可以尝试转义 bang 字符或使用以下不使用延迟扩展的版本。

@Echo Off

Set "Folder1=%UserProfile%\Desktop\Test Folder1"
Set "Folder2=%UserProfile%\Desktop\Test Folder2"

For /R "%Folder1%" %%x In (*.*) Do (
 Call :CompareFolder1 "%%x"
)

For /R "%Folder2%" %%x In (*.*) Do (
 Call :CompareFolder2 "%%x"
)

Pause
Exit /b

:CompareFolder1
 Set "FullPath=%~1"
 Call Set "RelPath=%%FullPath:%Folder1%=%%"
 If Exist "%Folder2%%RelPath%" (
  >Nul 2>&1 FC /b "%Folder1%%RelPath%" "%Folder2%%RelPath%" && (
   Echo Dup - %1
  )||(
   Echo Dif - %1
  )
 ) Else (
   Echo New - %1
 )
Exit /b

:CompareFolder2
 Set "FullPath=%~1"
 Call Set "RelPath=%%FullPath:%Folder2%=%%"
 If Not Exist "%Folder1%%RelPath%" (
  Echo New - %1
 )
Exit /b

1
投票

我对以下批处理文件的运气更好。 但路径名必须完全匹配;所以只有驱动器盘符不同。

映射共享网络文件夹可能会使这变得更容易。 我不能肯定你的情况。

'--- 设置本地 设置“folder1=D:\User\Public” 设置“Drv2=E:” 设置“文件掩码=*”

setlocal
 set "folder1=<DrvLttr>:\<Folder>\<SubFolder>"
 set "Drv2=<DrvLttr2>:"
 set "LogFile=<SystemDrv>\User\<UserName>\<LogFileName>"

ECHO "the '>' may OVER WRITE or make a ~NEW~ File for the results" > "%LogFile%"
ECHO " '>>' adds to the end of the file >> "%LogFile%"

FOR /R %folder1% %%A in ( *.* ) DO FC "%%A" "%Drv2%%%~pnxA" 1>> "%LogFile%" 2>&1

如果您想记下测试的命令是什么,您可以尝试在 DO 之后插入 ECHO。 您可以删除 1>>... 内容以在屏幕上查看结果,而不必打开输出文件。


1
投票

我修改了为 CD 过程编写的批处理文件,应该可以满足您的需求。 它

  • 获取 2 个目录树并比较每个树中的每个文件
  • 创建文件差异列表(在输出文件夹中名为 File_differences.txt)
  • 并为每个不匹配的对象创建一个包含差异文件的文件夹

如果两个目录结构位于同一父目录下,那么您所需要做的就是更新脚本中的前 8 个变量。 如果目录树有不同的父目录,请仔细阅读脚本注释。 特别是第 14、38 和 46 行。

:: This script compares the contents of 2 trees
:: set a workspace location for the script outside of the trees being reviewed
set home=D:\path\to\batch_file_home
set Input=D:\path\to\batch_file_home\Input_Files
set Resource=D:\path\to\batch_file_home\Resource_Files
set Output=D:\path\to\where your want to view your\Output_Files

set environment=D:\path\to\parent directory containing the different tree structures (if they do not share a parent, then make this the drive)
:: the next 3 lines are only needed if you want to predefine multiple directories for comparison 
set Prod=production
set QA=test
set Dev=branches\dev
:: If you remove the 3 lines above, then you need to replace the 2 below variables with values
:: If the trees are not under the same parent, then include the full path for Tree A and B below
set Tree_A=%Prod%
set Tree_B=%QA%
:: if you already have an object list, place it in the Input folder and remove lines 24 through 35 of this script
set Object_List=Object_List_minus_Direcotries.txt
set Output_File=File_differences.txt

if exist %Output%\%Output_File% del %Output%\%Output_File%
if exist %Output%\Differences\*.txt del %Output%\Differences\*.txt
if exist %Resource%\* del /q %Resource%\*

:: since you state the objects in both trees are always the same, I have not included a comparison to verify the 2 trees match
:: this section identifies the contents of Tree A
cd %environment%\%Tree_A%
dir /b /s > %Resource%\Complete_Tree_A_Object_List.txt

:: Next, remove the objects that are directories
setlocal enabledelayedexpansion
for /f "tokens=*" %%p in (%Resource%\Complete_Tree_A_Object_List.txt) do (
  dir /a:d /b %%p 2>nul >nul && (set object_type=folder) || (set object_type=file)
  echo !object_type!
  if !object_type!==file echo %%p >> %Resource%\%Object_List%
  )

:: in the object list, remove the parent tree from the path
:: if the Trees are not under the same parent, then comment out the below 6 lines
powershell -command "(Get-Content %Resource%\%Object_List%) -replace '\\','/' | set-content %Resource%\%Object_List%"
powershell -command "(get-content %Resource%\%Object_List%) | Foreach {$_.TrimEnd()} | Set-Content %Resource%\%Object_List%"
set remove_parent_prefix=%environment%\%Tree_A%
set remove_parent_prefix=%remove_parent_prefix:\=/%
powershell -command "(Get-Content %Resource%\%Object_List%) -replace '%remove_parent_prefix%/','' | set-content %Resource%\%Object_List%"
powershell -command "(Get-Content %Resource%\%Object_List%) -replace '/','\' | set-content %Resource%\%Object_List%"

:: the below loop assumes both Trees are under the same parent.  If this is not the case, replace the cd %environment% line with cd %home%
:: when the Trees are not under the same parent, set home to the root location, example cd D:\ 
setlocal enabledelayedexpansion
for /f "tokens=*" %%x in (%Resource%\%Object_List%) do (
  set Diff_File=%%x
  set Diff_File=!Diff_File:\=-!
  cd %environment%
  fc %Tree_A%\%%x %Tree_B%\%%x > "%Output%\Differences\!Diff_File!-%Output_File%"
  for %%a in ("%Output%\Differences\!Diff_File!-%Output_File%") do for /f %%b in ('find /c /v "" ^< "%%a" ') do if %%b LSS 3 del "%%a"  
  for %%R in ("%Output%\Differences\!Diff_File!-%Output_File%") do if not %%~zR lss 1 (
   echo %%x >> %Output%\%Output_File%
  )
  for %%R in ("%Output%\Differences\!Diff_File!-%Output_File%") do if %%~zR lss 1 (
     del "%Output%\Differences\!Diff_File!-%Output_File%"
  )
)
endlocal

:: Clean up Resources.  If you want to review the temp files used to create the report, comment out the below line
if exist %Resource%\* del /q %Resource%\*
© www.soinside.com 2019 - 2024. All rights reserved.