2

Я хочу сравнить два каталога (включая подпапки) для файлов (например, изображений) на двух отдельных дисках. У меня есть тысячи файлов, которые скрыты в подкаталогах и папках.

Маленький: пример

Скажем в C: ниже приведен список папок и файлов

C:\folder1
          file01.jpeg
          file02.jpeg

C:\folder1\folder2 
          file10.jpeg

C:\folder1\folder2\folder3 
          file04.jpeg
          file05.jpeg

C:\folder1\folder4

          file06.jpeg
          file07.jpeg
          file03.jpeg

D: имеет похожую структуру папок (может быть неточным, за исключением того, что папка 1 такая же), но некоторые файлы могут отсутствовать или быть дополнительными

D:\folder1
          file01.jpeg
          file08.jpeg

D:\folder1\folder2 
          file03.jpeg

D:\folder1\folder2\folder3 
          file04.jpeg

D:\folder1\folder4
          file06.jpeg
          file07.jpeg
          file09.jpeg

Теперь мне нужен быстрый способ (может быть, командная строка DOS или программное обеспечение, которое может найти отсутствующие или дополнительные файлы и поместить файлы в новый каталог, скажем, D:\diff

D:\difference
    file02.jpeg 
    file05.jpeg
    file08.jpeg 
    file09.jpeg
    file10.jpeg     

2 ответа2

5

Скрипт для перемещения файлов ниже ...

Если вы просто хотите увидеть, какие файлы одинаковые / разные, вы можете использовать windiff. Это может помочь в устранении проблем со сценарием.

Итак, для вашего примера:

C:> windiff c:\folder1 d:\folder1

Windiff откроет и покажет, какие файлы:

  • идентичный
  • Разное (указывает, какой файл новее)
  • Только слева (файл существует только в "первом пути" (C:\folder1)
  • Только справа (файл существует только по "второму пути" (D:\folder1)

Вы можете сохранить результаты в файл, используя параметр командной строки: -S:

-SS N:\path\filename.ext   [save list of identical files to filename.ext]
-SD N:\path\filename.ext   [save list of different files to filename.ext]
-SL N:\path\filename.ext   [save list of left-only files to filename.ext]
-SR N:\path\filename.ext   [save list of right-only files to filename.ext]

Также вы можете включить X с -S чтобы закрыть windiff после написания списка следующим образом:

-SRX N:\path\filename.ext   [save list of right-only files to filename.ext]

Вы можете комбинировать списки, поэтому, если вы хотите получить список файлов, которые существуют только по одному (любому) пути:

C:> windiff -SLRX leftrightonly.txt c:\folder1 d:\folder1

Вы можете создавать только один файл журнала одновременно, поэтому, если вы хотите сгенерировать все 4 отдельных файла журнала, вам нужно будет запустить windiff 4 раза:

C:> windiff -SSX same.txt c:\folder1 d:\folder1
C:> windiff -SDX different.txt c:\folder1 d:\folder1
C:> windiff -SLX leftonly.txt c:\folder1 d:\folder1
C:> windiff -SRX rightonly.txt c:\folder1 d:\folder1

Примечание. Файлы, которые существуют в обоих путях, но находятся в разных папках, будут отображаться как "leftonly" или "rightonly".



Если вы хотите, чтобы скрипт перемещал файлы, которые существуют только по одному из путей, в другую папку, вы можете использовать пакетный скрипт ниже.

Заметки:

  • Я называю файл, который существует только по одному из путей, "одиноким" файлом.
  • Приведенный ниже скрипт (с переменной "domove=0") будет отображать только "одинокие" файлы без их перемещения. После того, как вы проверили сценарий и убедились, что правильные файлы будут перемещены, вы можете изменить значение на: variable "domove=1" чтобы "одинокие" файлы отображались и перемещались.
  • В сценарии установите sdrive1, sdrive2, sfolder и sdifffolder при необходимости.
  • В качестве альтернативы, установите spath1, spath2 и spathdiff если это больше подходит для вашего использования.
  • При желании сценарий можно легко изменить, чтобы он принимал эти пути из командной строки.

Я сделал следующие предположения:

  • Для каждого файла в "первом пути" во всем "втором пути" ищется соответствующий «filename.ext».
  • Если файл НЕ найден во "втором пути" (одинокий файл), он перемещается в папку "разницы".
  • Не делается никаких попыток сравнить файлы с соответствующими именами файлов, но эту функциональность можно легко добавить.
  • Не предпринимаются попытки учесть возможность того, что несколько файлов могут иметь одинаковое имя и находиться в разных подпапках "первого пути" (то же самое для "второго пути"). Если это происходит для файла, который является "одиноким" файлом, каждый из этих файлов будет перемещен в папку "разности", перезаписывая все ранее перемещенные файлы с тем же именем.
  • После того, как каждый файл в "первом пути" ищется в "втором пути", процесс повторяется в другом направлении, и для каждого файла во "втором пути", весь "первый путь" ищется на соответствие «имяфайла.рсш».

Вот сценарий:

@echo off

rem use "domove" for testing
rem if "%domove%" !=1, "lonely" files found will only be displayed (not moved).
rem if "%domove%"  =1, "lonely" files found will be displayed and moved.
set "domove=0"

set "sdrive1=C:\"
set "sdrive2=D:\"
set "sfolder=folder1"
set "sdifffolder=difference"

set "spath1=%sdrive1%%sfolder%"
set "spath2=%sdrive2%%sfolder%"
set "spathdiff=%sdrive2%%sdifffolder%"
rem spath1=C:\folder1, spath2=D:\folder1, spathdiff=D:\difference

rem ***************************************************

rem check if "path1" and "path2" exist
if exist "%spath1%" if exist "%spath2%" goto :check2
if not exist "%spath1%" echo Error: Path1:"%spath1%" does not exist.>&2
if not exist "%spath2%" echo Error: Path2:"%spath2%" does not exist.>&2
goto :EOF



:check2

    rem check if "path1" is empty (no files)
    dir /a-d /s /b "%spath1%">nul 2>&1
    if %errorlevel% EQU 0 goto :check3
    echo Error: Path1:"%spath1%" is empty (no files).>&2
    goto :EOF



:check3

    rem check if "path2" is empty (no files)
    dir /a-d /s /b "%spath2%">nul 2>&1
    if %errorlevel% EQU 0 goto :check4
    echo Error: Path2:"%spath2%" is empty (no files).>&2
    goto :EOF



:check4

    rem check if "%spathdiff%" exists, but is a file (error)
    if not exist "%spathdiff%" goto :start
    if exist "%spathdiff%\*" goto :start
    echo Error: Folder "%spathdiff%" conflicts with a file with the same name.>&2
    goto :EOF



:start

    rem get a list of all files in "first path", call :work1
    rem passing "(path1:)C:\path\...\filename.ext", "filename.ext", and "D:\path2"
    for /f "usebackq delims=" %%f in (`dir /s /b /a-d "%spath1%"`) do call :work1 "%%~f" "%%~nxf" "%spath2%"

    rem reverse the paths:
    rem get a list of all files in "second path", call :work1
    rem passing "(path2:)D:\path\...\filename.ext", "filename.ext", and "C:\path1"
    for /f "usebackq delims=" %%f in (`dir /s /b /a-d "%spath2%"`) do call :work1 "%%~f" "%%~nxf" "%spath1%"

    rem done, exit
    goto :EOF



:work1

    set "w1full=%~1"
    set "w1file=%~2"
    set "wpath2=%~3"

    rem "%w1file%" is the "target" "filename.ext" from "first path" to look for (in "second path").
    for /f "usebackq delims=" %%g in (`dir /s /b /a-d "%wpath2%"`) do call :work2 "%%~nxg" "%w1file%" "w1file"

    rem if "target" "filename.ext" from "first path" was found in the "second path",
    rem it is now empty. it means:
    rem file is somewhere in both paths... no action. go get next file from "first path"
    if "%w1file%."=="." goto :EOF

    rem at this point, "%w1file%" ("%w1full%") is a "lonely" file
    rem "%w1file%" only exists in "path1" move it to "difference" path
    rem additional checks might be necessary here
    rem to see if this file already exists in "difference" path
    if not exist "%spathdiff%" md "%spathdiff%">nul 2>&1
    echo Found "lonely" file %w1file%:   move "%w1full%" "%spathdiff%"
    if %domove% EQU 1 move /y "%w1full%" "%spathdiff%">nul 2>&1
    rem you can test %errorlevel% here for error: %errorlevel%=0 if no error

    rem go get next file from "first path"
    goto :EOF



:work2

    rem %1 is "current" "filename.ext" from "second path"
    rem %2 is "target" "filename.ext" from "first path"

    rem if "target" "filename.ext" is empty, return for more
    if "%~2."=="." goto :EOF

    rem if file from "first path" is found in "second path", 
    rem "clear" the variable holding the filename of the "target" "filename.ext" from "first path"
    rem additional checks might be necessary here
    rem to "compare" the two files
    if /I "%~1"=="%~2" set "%~3="
    goto :EOF

Вот результат тестирования скрипта с примером набора файлов, который вы описали:

Found "lonely" file file02.jpeg:   move "c:\folder1\file02.jpeg" "d:\difference"
Found "lonely" file file10.jpeg:   move "c:\folder1\folder2\file10.jpeg" "d:\difference"
Found "lonely" file file05.jpeg:   move "c:\folder1\folder2\folder3\file05.jpeg" "d:\difference"
Found "lonely" file file08.jpeg:   move "d:\folder1\file08.jpeg" "d:\difference"
Found "lonely" file file09.jpeg:   move "d:\folder1\folder4\file09.jpeg" "d:\difference"
3

Если ваша цель просто определить, какие файлы присутствуют в одной папке, и скопировать их, тогда вы можете использовать программу синхронизации файлов . Есть много, которые могут сделать эту работу.

Программа сравнения папок определенно хороша для лучшего контроля, потому что вы можете просматривать различия, и они обычно также имеют более точные параметры сравнения. Вы указали, что вы просто хотите скопировать файлы, а не получить список или интегрировать их в скрипт, поэтому программа с графическим интерфейсом, вероятно, идеально подходит для вашей ситуации.

Одним из лучших для этой цели будет WinMerge. Он не только позволяет сравнивать содержимое двух каталогов и предоставлять различные фильтры, например скрывать идентичные файлы, но и позволяет чрезвычайно легко копировать нужные файлы (рисунок 1).

Он также активно развивается, поэтому вы можете подавать отчеты об ошибках и запросы функций. Лучше всего, это бесплатно.


Рисунок 1: WinMerge имеет несколько методов для синхронизации файлов

Снимок экрана WinMerge с несколькими способами синхронизации файлов

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .