fdupesは重複ファイルを手軽に削除できるコマンドだが,fdupesで削除する対象から自動的に除外できるのは重複リストの内一番上のファイルだけ.
一番下のものを残したいときは
- 重複リスト作成
- 削除リスト作成(ここで一番下のファイルを除外する)
- rm
の順に行う
インストールしておくコマンド
- fdupes
- pcregrep ... PCREパッケージをインストールすると入っている…筈
grep -Pzo
でも良いかもしれないが,どうしても空行が残ってしまったのでpcregrep
を使った.
そもそもBSD-grepなどはPCRE未対応なので,特にマカーさんはpcregrep
をbrew
等で入れておくのがお勧め.
(awkerの方々から飛んでくる鉞はキャッチしたい)
重複ファイルリスト作成
[fdupes
]
- -q: プログレスインジケーターを出力しない
- -r: ディレクトリ内を再起検索
単一ディレクトリ
fdupes -qr ./ > "./duped.txt"
複数ディレクトリ
各ディレクトリ毎に重複を検出したいなら関数かスクリプトを用意する
if [ $# -ne "1" ]; then
exit 1
fi
fdout=`fdupes -qr "./$1"`
if [ ${#fdout} -ne "0" ]; then
echo -e "${fdout}\n" > "./duped-$1.txt"
fi
プロセス数はお好みで
ここでは削除時以外-P 4
で4つフォークさせます
[xargs
]
- -P: 同時に実行できる最大プロセス数
- -d: デリミタを指定
ls -1 | xargs -d '\n' -P 4 -I@ fdupesout "@"
重複がなかったときに空ファイルが生成されても良いと言う場合は
ls -1 | xargs -P 4 -I@ sh -c 'fdupes -qr "./@" > "./duped-@.txt"'
だけでも可
削除リスト作成
重複データ毎に改行が入るので,次の行が改行だけでない行を抽出しファイルに出力
ディレクトリ毎に重複リストが分割してあるなら先に
cat duped-* > duped.txt
でまとめる.そのためには重複リストの末尾には改行を追記しておくこと.
[pcregrep
]
- -u: UTF-8モード(を使うと何故かエラー)
- -M: 複数行を対象に検索.改行
\n
が使用可能に
pcregrep -M '[^\n]+\n(?!\n|$)' duped.txt > rmlist.txt
これで重複結果の内一番下のファイルを残すことができる
ディレクトリ毎削除リスト
ディレクトリ毎に分割した重複リストを元に削除リストもディレクトリ毎に分割するなら
[xargs
]
- -I{置換文字}: プレースホルダを設定.
ls -1 duped-* | xargs -P 4 -I@ sh -c 'pcregrep -M "[^\n]+\n(?\!\n|$)" @ > "rm-@.txt"'
※注意
- マルチプロセスで実行した結果を1つのファイルに書き込むと希に出力が混ざって壊れるので,上記のように一度別のリストに出力した後
cat
でまとめるか,リスト毎に削除を行う方が良い. - xargsでpcregrepを使う場合は「!」をエスケープすること
削除
xargs -d '\n' -I@ rm "@" < rmlist.txt
ゴミをこさえたくないなら
※ 処理規模が小さいなら以下のワンライナーでもできるかも知れない
fdupes -qr ./ | pcregrep -M '[^\n]+\n(?\!\n|$)' | xargs -d '\n' -I@ rm "@"