スマートフォンやデジカメで撮影した写真やビデオは、PCに取り込んでバックアップ・管理しますが、 スマホやカメラで見たいこともあり、一部または全部をメモリーカードに残しておくことがあります。 また、地図やパンフレットなどの PDF ファイルをダウンロードして保存することもありますが、 保存先を忘れて同じものをダウンロードしてしまうこともあるでしょう。
すると、どうしても重複してハードディスクに取り込んでしまうファイルが出てきます。 それを探すのは面倒なわけですが、ファイル名が異なっている(別名で保存していまっている)場合には、もっと大変です。 放置すればHDD容量を圧迫していきますし、重複保存していると思って削除したら重複していなかった、となるとショックです。
この手のツールは探せばすぐ見つかりますが、簡単な構造ですから、自作しました。 ツールとしてというより、忘れやすいコードを中心に、ここに記載しています。
このページにトピック一覧がありますので、あわせてご参照ください。
このソフトおよびコードは Windows 用ですので、 PC向けデザインとなっております。 画面サイズの小さいスマホでは、快適な表示が得られませんので、ご了承ください。
また、ご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
投稿 November 15, 2018
特に画像やビデオといったデータ種別(フォーマット)にとらわれることなく、 指定のフォルダ(およびそのサブフォルダ)にあるファイルを検索し、重複ファイルを検索します。
同一ファイル名のものであれば、(相当古いマイクロソフトのツール)WinDiff などのユーティリティを使ってフォルダ単位で比較できますが、 ファイル名が変わっていたり、タイムスタンプが変わっていると、そう簡単にはいきません。
このプログラムは、指定したフォルダ(オプションでサブフォルダも含められます)にあるファイルをすべて検査し、
ファイル名、拡張子、タイムスタンプなどすべて関係なく、
ツール系ではよく使う、「参照...」ボタンからのフォルダの指定、
あるいはエクスプローラ等からのドロップ受付処理、
フォルダを(エクスプローラで)開く処理、ファイルを(関連付けられたプログラムで)開く処理などのコードが含まれています。
また、長い処理に入ったときの中止処理を、(このプログラムはちゃんとしていませんが)入れてあります。
Win7 + Visual C++ 2013/MFC で、ダイアログアプリとして作成しています。
投稿 November 15, 2018
起動すると、次のような画面が表示されます。
左上の「検索対象フォルダ」欄に、検索対象のフォルダ名を入力します。
すぐ右の「参照...」ボタンを押してフォルダを選択するか、このダイアログにフォルダをドロップしても入力できます。
サブフォルダも検索したい場合は、「サブフォルダを含める」にチェックを入れます。 初期状態はチェックされていない(サブフォルダを含めない)設定となっています。 なお、サブフォルダも検索する場合、処理時間が長くなる可能性がありますので、注意が必要です。
「検出する」ボタンを押すと、右側の空欄(リストボックス)に見つかったファイルがリストアップされ、 完了すると消去され、すぐ続けて重複ファイルの検索が始まり、その結果が出力されます。
重複ファイル数とそのファイル名(最初に見つかったもの)が表示されますので、ダブルクリックで詳細を見られます。
ダブルクリックで新しいダイアログが開き、 2つのファイルが重複している場合(同一ファイルが2つある場合)、次のようにリストに2アイテムが表示されます。
1つを選択して「フォルダを開く」ボタンを押すと、そのファイルを含むフォルダが開かれます。
アイテムをダブルクリックすると、関連付けられたプログラムでそのファイルを開きます。
「閉じる」ボタンを押して前の画面に戻り、「選択項目を削除」すると、結果リストからその項目が削除されます。
いずれの場合も、ファイル自体は削除されません。
本プログラムでは同一であると結論付けていますが、本当に削除するかどうかはあくまで使用者の責任となります。
なお、私なら、完全に信用できるサイト以外からのダウンロードはしませんが、
興味がある方のために、実行ファイルを圧縮したものを置いておきます。
安全に努めているマシンで用意したファイルですが、お試しいただく場合は、完全に自己責任でお願いします。
OSは Windows 7 以降、ランタイムなど環境の用意は
実行ファイルを含む zip ファイルのダウンロードは、
https://www.straightapps.com/download/duplifiledetector.zip
正しい zip ファイルのタイムスタンプは 2018/11/15 11:59:29、
正しい実行ファイルのタイムスタンプ(更新日時)は 2018/11/15 11:54:27 で、
zip 内は実行ファイル1つだけです。
zip ファイルサイズは 1,859,391 バイト、
実行ファイルのサイズは 3,333,632 バイトです。
パスワードは設定していません。
投稿 November 15, 2018
「参照...」ボタン処理で、フォルダの選択ダイアログを表示し、選択されたフォルダを取得しています。
次のようなコードを入れています。
#include "shlobj.h" void CDupliFileDetectorDlg::OnClickedBrowse() { BROWSEINFO bi; LPITEMIDLIST itemID; TCHAR szDir[MAX_PATH]; TCHAR szFile[MAX_PATH]; ZeroMemory(&bi, sizeof(BROWSEINFO)); ZeroMemory(szDir, MAX_PATH); ZeroMemory(szFile, MAX_PATH); bi.hwndOwner = GetSafeHwnd(); // オーナーウィンドウのハンドル bi.pidlRoot = NULL; // ルートフォルダのIDリスト bi.pszDisplayName = szFile; // 選択フォルダのパス bi.lpszTitle = _T("フォルダを選択して下さい"); // 表示テキスト bi.ulFlags = BIF_RETURNONLYFSDIRS; // フォルダのみ選択 bi.lpfn = NULL; // コールバック関数 bi.lParam = 0; // コールバック関数に渡される値 bi.iImage = 0; // 選択フォルダのイメージリストインデックス if (itemID = SHBrowseForFolder(&bi)){ SHGetPathFromIDList(itemID, szDir); CoTaskMemFree(itemID); SetDlgItemText(IDC_FOLDER_1, szDir); } }
GlobalFreePtr 関数を呼び出して itemID を解放すべきという記述をネットで見つけているのですが、 今はこの関数はありません。 今は CoTaskMemFree 関数を使用して IDList を解放する、ということです。
なお、この SHBrowseForFolder 関数は「ファイルを開くダイアログのフォルダモード」であり、 Windows Vista 以降では IFileDialog 関数に FOS_PICKFOLDERS を指定して使うべき、とされているようです。
投稿 November 15, 2018
ファイルのドロップを受け入れるには、ダイアログのプロパティで Accept Files を True にしておく必要があります。
そのダイアログに WM_DROPFILES メッセージのハンドラーを追加して、 受付処理を実装します。
void CDupliFileDetectorDlg::OnDropFiles(HDROP hDropInfo) { TCHAR szBuffer[MAX_PATH]; // ドロップされたファイル数を検査します。 UINT unDropped = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0); if (unDropped < 1){ // 安全のため、ドロップファイルなしを除外します return; // 続きの処理は行いません } // 2つ以上のファイルがドロップされた場合は警告を表示します。 if (unDropped ≷= 2){ CString strMsg; strMsg.Format(_T("2つ以上のファイルがドロップされました。\n\n一度に検査できるのは1フォルダのみです。")); MessageBox(strMsg, _T("検索フォルダのドロップ"), MB_ICONEXCLAMATION | MB_OK); return; } // ドロップファイル処理 for (UINT i = 0; i < unDropped; i++){ // ファイルを順次検査 DragQueryFile(hDropInfo, i, szBuffer, MAX_PATH); // ドロップされたファイル名を取得 SetDlgItemText(IDC_FOLDER_1, szBuffer); // エディットコントロールに登録 } }
OnDropFiles 関数が受領したハンドル hDropInfo を使って、
ドロップされたファイル(フォルダ)数を取得し、ループ内でそれを取得しています。
2つ以上を受け付けなくしていますので、最後の部分でループでまわす必要はありませんが、
影響はありませんので、このままとしています。
投稿 November 15, 2018
特に「サブフォルダを含める」にチェックを入れて検索を行ったとき、 重複ファイル数が多かったり、ビデオなどの大きいサイズのファイル比較が多くあった場合など、 長時間かかる場合があります。
基本的には、自分のみ利用するツールとして開発していますので、ワーカースレッドを作成して中断可能、のようにはしていません。 しかし、開発中など検索を中断したいケースもありました。そこで、非常に簡易的に、中断できる仕組みを入れてあります。
検索処理が長くなり、中断したいとき、もう1回この実行ファイルを起動すると、すでに起動されていることを検出し、 中断イベントを発行するか、問い合わせが行われます。中断イベントを発行すると、ループ内でそれを検知して中断する、 という仕組みになっています。
詳細は、「イベントによる簡易的な処理中止指示」をご覧ください。
投稿 November 15, 2018
その他のコードは、別ページに分離して書いています。各リンクより、トピックに飛べるようになっています。
エクスプローラーでフォルダを開くコードは、「フォルダやファイルを開く」の ここに、 関連付けられたプログラムでファイルを開くコードは、上と同じトピック内のここに書いています。
DaysUntil は、指定の日まであと何日かを計算する Windows デスクトップ・ユーティリティです。日数の計算や、うるう年の判定コードなどが入っています。
PCからSDカードに転送した音楽データが見えない
Android 9.0 で、PC から SD カードに転送した音楽データが、Play Music アプリで見えない問題について、書いています。
Windows に関する記事をまとめた Windows トップ もご覧ください。