燕南的網絡日誌 http://meng6net.localhost/zh/blog/ <p><small>© 2005-2020 <code>陸萌 &lt;lumeng3@gmail.com&gt;</code></small></p> 陸燕南的博客 ikiwiki Tue, 16 May 2017 23:59:39 +0000 找重複文件的Bash程序 http://meng6net.localhost/zh/blog/%E6%89%BE%E9%87%8D%E8%A4%87%E6%96%87%E4%BB%B6%E7%9A%84Bash%E7%A8%8B%E5%BA%8F/ http://meng6net.localhost/zh/blog/%E6%89%BE%E9%87%8D%E8%A4%87%E6%96%87%E4%BB%B6%E7%9A%84Bash%E7%A8%8B%E5%BA%8F/ bash 命令行 工具 文件 編程 重複 Tue, 16 May 2017 23:59:39 +0000 2017-05-16T23:59:39Z <p>寫了一個找重複文件的 Bash 腳本,通過比較文件大小和<a href= "http://zh.wikipedia.org/zh-hant/%E6%A0%A1%E9%AA%8C%E5%92%8C">校验和</a>來判斷文件是否(可能)是重複的:</p> <h2>程序</h2> <pre><code>#!/usr/bin/env bash ## Summary: find duplicate files ## Meng Lu &lt;lumeng.dev@gmail.com&gt; DIR=${1:-`pwd`} ## use provided path if available, otherwise the current path FILENAME=`basename $0` TMPFILE=`mktemp /tmp/${FILENAME}.XXXXXX` || exit 1 ## one-line version #find -P . -type f -exec cksum '{}' \; | sort | tee $TMPFILE | cut -f 1-2 -d ' ' | uniq -d | grep -if - $TMPFILE | sort -nr -t' ' -k2,2 | cut -f 3- -d ' ' | while read line; do ls -lhta "$line"; done ## multi-line version with comments find -P . -type f -exec cksum '{}' \; | # find non-directory files and compute their checksum; -P: never follow symbolic links sort | # sort by {checksum, file size, file name} tee $TMPFILE | # save a copy in a temporary file and pass along cut -f 1-2 -d ' ' | # keep only the checksum and file size uniq -d | # remove uniq ones grep -if - $TMPFILE | # greps from previously saved file list the lines of duplicate files identified by having same file size and checksum; - is from redirecting stdout to stdin sort -nr -t' ' -k2,2 | # sort by descending file size cut -f 3- -d ' ' | # keep only file name while read line; do ls -lhta "$line"; done # do informative ls on all found duplicate files </code></pre> <p><a href= "https://github.com/lumeng/repogit-mengapps/blob/master/file-system/find-duplicate-files.sh"> GitHub 存檔</a>。</p> <h2>註釋</h2> <ul> <li><code>find -P . -type f -exec cksum '{}' \;</code> <ul> <li><code>-P</code> 不找符號鏈接文件(symbolic links);</li> <li><code>-type f</code> 找文件而非文件夾;</li> <li><code>-exec cksum '{}' \;</code> 對每個找到的文件(<code>'{}'</code>)計算校驗和,<code>cksum</code> 輸出<code>校驗和 文件大小 文件名</code>,其中文件大小是八進制數個數;</li> </ul> </li> <li><code>sort</code> 排序,爲 <code>uniq</code> 做準備;</li> <li><code>tee $TMPFILE</code> 把 <code>stdout</code> 流的內容一方面保存到臨時文件,一方面繼續沿着 pipe 傳遞到下游;</li> <li><code>cut -f 1-2 -d ' '</code> 只保留第1、2欄,欄目以空格分;</li> <li><code>uniq -d</code> 刪除唯一的亦即無重複的行;</li> <li><code>grep -if - $TMPFILE</code> 通過 <code>-</code> 將輸出流轉換爲輸入流,在預存的文件目錄中找重複文件的{校驗和,文件大小}出現的行,注意,這裏的行包含文件名;</li> <li><code>sort -nr -t' ' -k2,2</code> 對找出的重複的文件按大小降序排序;</li> <li><code>cut -f 3- -d ' '</code> 之保留保留文件名;</li> <li><code>while read line; do ls -lhta "$line"; done</code> 對每一文件打印詳細信息。</li> </ul> <h2>相關文章</h2> <ul> <li><a href="http://meng6net.localhost/computing/example/examples_of_using_find/">find 應用實例</a></li> <li><a href="http://meng6net.localhost/computing/example/examples_of_using_grep/">grep 應用實例</a></li> </ul>