::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: Name: 搜索重復圖片(或其他任意類型、大小的文件,對0字節(jié)的也比較)
::
:: Author: NeedJava
::
:: Modified: 2007-07-30
::
:: 注意:你可以在任何地方使用此批處理,但必須保持文件作者及注釋部分的完整
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@ECHO OFF
SETLOCAL EnableDelayedExpansion
ECHO 搜索重復的圖片,按任意鍵繼續(xù)。
ECHO.
PAUSE>NUL
DEL /F /Q hash.txt 2>NUL
DEL /F /Q sort.txt 2>NUL
DEL /F /Q clone.txt 2>NUL
DEL /F /Q lost.txt 2>NUL
RD /S /Q "Clone\" 2>NUL & MD "Clone\" 2>NUL
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: 生成“文件大小|文件路徑”,再排序,內(nèi)容諸如:
::
:: 25329|C:\Documents and Settings\Administrator\桌面\02.jpg
::
:: 把文件大小加上100000000,即100MB,這樣方便SORT命令比較大小,那么內(nèi)容變成如下:
::
:: 100025329|C:\Documents and Settings\Administrator\桌面\02.jpg
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CLS
ECHO 正在搜索文件,請稍候……
ECHO.
FOR /R %%a IN ( *.jpg ) DO (
??? SET /A size=%%~za+100000000
??? ECHO !size!^|%%a>>hash.txt
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: 根據(jù)列表每行前面所列出的文件大小進行排序
::
:: 把文件大小加上100000000,即100MB,這樣方便SORT命令比較大小
::
:: 否則SORT會給我們“1、123、1235、2、21、3”這樣的順序
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CLS
ECHO 正在排序文件,請稍候……
ECHO.
IF EXIST hash.txt (
?? SORT /R hash.txt /O sort.txt 2>NUL
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: 把大小相同的文件分離成一個個單獨的文件,方便后面的相互比較
::
:: 我不認為需要對5MB以上的圖片文件進行二進制比較,它們夠顯眼的了
::
:: 只有大小一樣才需要作進一步的二進制比較,否則就是搞笑了
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CLS
ECHO 正在分離文件,請稍候……
ECHO.
IF EXIST sort.txt (
?? SET "preSize="
?? SET "preFile="
?? FOR /F "tokens=1,2 delims=|" %%a IN ( sort.txt ) DO (
?????? SET /A curSize=%%a-100000000
?????? SET "curFile=%%b"
?????? IF NOT "!preFile!"=="" IF !preSize! LEQ 5000000 (
????????? IF !preSize! EQU !curSize! (
???????????? IF /I NOT "!always!"=="true" (
??????????????? ECHO !preSize!^|!preFile!>"Clone\!preSize!.vab"
??????????????? SET "always=true"
???????????? )
???????????? ECHO !curSize!^|!curFile!>>"Clone\!preSize!.vab"
????????? ) ELSE (
??????????? SET "always=false"
????????? )
?????? )
?????? SET /A preSize=!curSize!
?????? SET "preFile=!curFile!"
?? )
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: 微軟一些DOS命令的搞笑BUG:
::
:: FC:名稱的字數(shù)超過185個的文件夾不予理會
::
:: DIR:把路徑中的一些Unicode碼(如30FB)用半角問號“?”代替,記事本也如此
::
:: FOR /R:不但把Unicode碼(如30FB)用半角問號“?”代替,還會刪除路徑中的“!”和“^”
::
:: 以上這些微軟BUG,使這個批處理也有了BUG:路徑中不能有“!”、“^”和一些Unicode碼
::
::
:: FC命令返回代碼含義:
::
:: 0?? 完全相同
::
:: 1?? 不完全同
::
:: 2?? 缺少文件
::
::
:: FIND命令返回代碼含義:
::
:: 0?? 找到字符串
::
:: 1?? 沒有找到字符串
::
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:reload
IF EXIST "Clone\" (
?? FOR /R "Clone\" %%a IN ( *.vab ) DO (
?????? SET "list=Clone\%%~nxa"
?????? SET /A num=1
?????? GOTO cycle
?? )
)
GOTO delete
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: 原理:
::
:: 假設(shè)有DATA[A B C D B A A]這個7位數(shù)組需要自身比較,按照正常的方法,如下:
::
:: for( int i=0; i<n-1; i++ )
::??? {
::????? for( int j=i+1; j<n; j++ )
::???????? {
::?????????? compare DATA[i] DATA[j]...
::???????? }
::??? }
::
:: 需要比較N*(N-1)/2次,即7*(7-1)/2=21次,如下:
::
:: [A B]、[A C]、[A D]、[A B]、[A A]、[A A]
::
:: [B C]、[B D]、[B B]、[B A]、[B A]
::
:: [C D]、[C B]、[C A]、[C A]
::
:: [D B]、[D A]、[D A]
::
:: [B A]、[B A]
::
:: [A A]
::
:: 但是從上面的列表可以發(fā)現(xiàn),有些已經(jīng)被確定和某個數(shù)相同的數(shù),如[A]和[B]兩類,
::
:: 在后面依然和別的數(shù)繼續(xù)比較,這是不科學的,應(yīng)該在找到相同類后,刪除它們。
::
:: 也就是說,一旦找到相同的類,就把它們剔除出循環(huán),那么循環(huán)應(yīng)該如下:
::
:: A B C D B A A
::
:: 第一次循環(huán)找出所有相同的[A]后,待比較列表動態(tài)變?yōu)椋?br />::
:: B C D B
::
:: 第二次循環(huán)找出所有相同的[B]后,待比較列表動態(tài)變?yōu)椋?br />::
:: C D
::
:: 如上,那么比較為:
::
:: [A B]、[A C]、[A D]、[A B]、[A A]、[A A]
::
:: [B C]、[B D]、[B B]、[BXA]、[BXA]
::
:: [C D]、[CXB]、[CXA]、[CXA]
::
:: [DXB]、[DXA]、[DXA]
::
:: [BXA]、[BXA]
::
:: [AXA]
::
:: 中間有X的表示已被縮減的,即最終比較為:
::
:: [A B]、[A C]、[A D]、[A B]、[A A]、[A A]
::
:: [B C]、[B D]、[B B]
::
:: [C D]
::
:: 整個批處理原理:
::
:: 1、FOR命令通過%%~za生成零散的,每列開頭為文件大小的文件列表hash.txt,如:
::
::??? 100017000|E:\123.jpg
::??? 100017000|E:\345.jpg
::??? 100056732|E:\ffff.jpg
::??? 100017000|E:\OK\123.jpg
::??? 100056732|E:\OK\ffff.jpg
::??? 100012345|E:\OK\gag.jpg
::
:: 2、SORT命令將hash.txt從大到小(當然也可以從小到大)排序成sort.txt,如:
::
::??? 100056732|E:\ffff.jpg
::??? 100056732|E:\OK\ffff.jpg
::??? 100017000|E:\123.jpg
::??? 100017000|E:\345.jpg
::??? 100017000|E:\OK\123.jpg
::??? 100012345|E:\OK\gag.jpg
::
:: 3、分析sort.txt列表文件,如果有兩行以上大小相同的紀錄,分離到同一個新列表文件:
::
::??? 文件名:Clone\56732.vab,內(nèi)容如下:
::??? 100056732|E:\ffff.jpg
::??? 100056732|E:\OK\ffff.jpg
::
::??? 文件名:Clone\17000.vab,內(nèi)容如下:
::??? 100017000|E:\123.jpg
::??? 100017000|E:\345.jpg
::??? 100017000|E:\OK\123.jpg
::
:: 4、通過雙層嵌套FOR命令,進行比較,相同的紀錄進clone.txt,也就是最終文件;
::
::??? 不相同的則紀錄進新的文件comparedN.vab,此處N為數(shù)字1、2、3、4,如果不刪除,
::
::??? 可以看到動態(tài)的待比較列表,用于調(diào)試。
::
::??? 一旦生成了comparedN.vab文件,就表示有未比較的文件,則將待比較列表list設(shè)成
::
::??? 最新的comparedN.vab文件,并且跳轉(zhuǎn)到雙層嵌套FOR命令開頭cycle,重新循環(huán)。
::
::??? 一旦待比較列表list消失,則表明此類大小的文件比較完畢,跳轉(zhuǎn)到reload,分析下
::
::??? 一個大小的文件列表。
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:cycle
REM TYPE !list! & PAUSE
IF EXIST !list! (
?? FOR /F "tokens=1,2 delims=|" %%M IN ( !list! ) DO (
?????? SET "found=false"
REM??? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM??? ::
REM??? :: 我們分析的文件內(nèi)容是用“|”分隔的,如下:
REM??? ::
REM??? :: 56732|E:\ffff.jpg
REM??? ::
REM??? :: tokens=1,2 delims=|會把內(nèi)容分割成兩部分,即56732和E:\ffff.jpg
REM??? ::
REM??? :: 第一個部分用變量%%m表示,也就是文件大小56732
REM??? ::
REM??? :: 第二個部分用變量%%n表示,也就是文件完整的路徑E:\ffff.jpg
REM??? ::
REM??? :: skip=1表示跳過一行,用來防止自身比較。當然為了穩(wěn)妥,下面還是用了判斷
REM??? ::
REM??? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
?????? FOR /F "skip=1 tokens=1,2 delims=|" %%m IN ( !list! ) DO (
REM??????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM??????? ::
REM??????? :: 必須是大小相同的文件才能比較。不是必要,但穩(wěn)妥起見還是判斷一下
REM??????? ::
REM??????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
?????????? IF /I "%%M"=="%%m" (
REM?????????? ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM?????????? ::
REM?????????? :: 不能自己跟自己比較。雖然上面用skip=1跳過,但穩(wěn)妥起見還是判斷一下
REM?????????? ::
REM?????????? ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
????????????? IF /I NOT "%%N"=="%%n" (
???????????????? CLS
???????????????? ECHO 正在比較以下%%M字節(jié)的兩個文件:
???????????????? ECHO %%N
???????????????? ECHO %%n
???????????????? ECHO.
REM????????????? PAUSE
REM????????????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM????????????? ::
REM????????????? :: 根據(jù)FC命令用二進制比較,所返回的錯誤碼來判斷兩個文件是否相同
REM????????????? ::
REM????????????? :: Windows 2000下FC命令有問題,所以Windows 2000不能使用此批處理
REM????????????? ::
REM????????????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
???????????????? FC.EXE /B "%%N" "%%n">NUL 2>NUL
REM????????????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM????????????? ::
REM????????????? :: 兩個文件比較后完全相同,F(xiàn)C命令會返回0
REM????????????? ::
REM????????????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
???????????????? IF !ERRORLEVEL! EQU 0 (
??????????????????? ECHO 兩個文件完全相同!
??????????????????? ECHO.
REM???????????????? PAUSE
REM???????????????? ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM???????????????? ::
REM???????????????? :: 如果!found!為true,就表示在比較循環(huán)中,遇到了第一次相同
REM???????????????? ::
REM???????????????? :: 用于在找到的列表clone.txt中寫入新的標題
REM???????????????? ::
REM???????????????? ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
??????????????????? IF /I NOT "!found!"=="true" (
?????????????????????? ECHO [%%M Bytes]>>clone.txt
?????????????????????? ECHO %%N>>clone.txt
?????????????????????? SET "found=true"
??????????????????? )
??????????????????? ECHO %%n>>clone.txt
???????????????? )
REM????????????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM????????????? ::
REM????????????? :: 兩個文件比較后不相同,F(xiàn)C命令會返回1
REM????????????? ::
REM????????????? :: 把不相同的文件寫入下一個待比較列表
REM????????????? ::
REM????????????? :: 這個列表將取代現(xiàn)有列表用于下次循環(huán)
REM????????????? ::
REM????????????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
???????????????? IF !ERRORLEVEL! EQU 1 (
REM???????????????? ECHO %%n & ECHO. & PAUSE
??????????????????? ECHO %%m^|%%n>>"compared!num!.vab"
???????????????? )
REM????????????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM????????????? ::
REM????????????? :: 找不到相應(yīng)的文件時,F(xiàn)C命令會返回2
REM????????????? ::
REM????????????? :: 由于FOR /R命令得出的路徑,會刪除路徑中的“!”和“^”,
REM????????????? ::
REM????????????? :: 這會導致雖然待比較列表有路徑(錯誤的),然而FC命令卻找不到
REM????????????? ::
REM????????????? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
???????????????? IF !ERRORLEVEL! EQU 2 (
REM???????????????? ECHO %%n & ECHO. & PAUSE
??????????????????? IF NOT EXIST "%%N" (
?????????????????????? ECHO %%M^|%%N>>lost.txt
??????????????????? )
??????????????????? IF NOT EXIST "%%n" (
?????????????????????? ECHO %%m^|%%n>>lost.txt
??????????????????? )
???????????????? )
????????????? )
?????????? )
?????? )
REM??? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM??? ::
REM??? :: 如果!found!為true,就表示在這次循環(huán)中找到了相同文件
REM??? ::
REM??? :: 那么針對這次循環(huán)的結(jié)束,在找到的列表clone.txt中追加一個空行,用來分隔
REM??? ::
REM??? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
?????? IF /I "!found!"=="true" (
????????? ECHO.>>clone.txt
?????? )
REM??? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM??? ::
REM??? :: 刪除現(xiàn)有的待比較列表,必須刪除,否則會陷入死循環(huán)
REM??? ::
REM??? :: 這也是跳出循環(huán)的判斷條件,very important!
REM??? ::
REM??? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
?????? DEL /F /Q "!list!" 2>NUL
REM??? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
REM??? ::
REM??? :: 如果剛才的循環(huán),有一些文件不相同,就會存在新的待比較列表
REM??? ::
REM??? :: 我們把它設(shè)為新的待比較列表,準備跳轉(zhuǎn)到循環(huán)開頭,重新循環(huán)
REM??? ::
REM??? :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
?????? IF EXIST "compared!num!.vab" (
????????? SET "list=compared!num!.vab"
????????? SET /A num+=1
?????? ) ELSE (
???????? GOTO reload
?????? )
?????? GOTO cycle
?? )
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: 刪除用過的文件
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:delete
DEL /F /Q hash.txt 2>NUL
DEL /F /Q sort.txt 2>NUL
RD /S /Q "Clone\" 2>NUL
IF EXIST clone.txt %SystemRoot%\NOTEPAD.EXE clone.txt
@ECHO ON
posted on 2007-07-30 13:20
NeedJava 閱讀(637)
評論(0) 編輯 收藏 所屬分類:
DOS Windows