#背景
長年のPC歴によって、様々なファイルを様々なメディアに保存してきた。いい加減に統一してしまいたいのでNASを導入して次々と個別のメディア(USBフラッシュ, HDD, MO!, FDD!! etc.)からコピーしている(進行形)。古いメディアの殆どは低容量だし、場所も取るので廃棄中。
困るのは、PCを移行する度にHDDごと保管していたデータ。多くは前のPCから引き継いで引き継いで...×n..。重複ファイルが大量にある。持ち出し用にコピーしていたメディアにも大量に重複があるし、バージョン違いもあってカオス。
ひとまず1メディアに1ディレクトリを割り当ててコピーするだけしているが、やはりNASも有限なのでせめて同一ファイルは除去していきたいと思った。
#解法
20240319追記:WindowsならWinMergeがお勧め!
世の中には優秀なツールが沢山あるようだが、無料で良い物を探す気力が無い。そこで、ある程度自動かつ自分の目で確認しながら重複除去をするためのスクリプトを作成して対処している。
前提:UNIXライクな環境 (GNU系列のコマンド体系)
rdfindインストール済み
#!/bin/bash
# Usage: mergehelper.sh DIR1 DIR2
DIR1=$1
DIR2=$2
rdfind -ignoreempty true -dryrun true ${DIR1} ${DIR2}
grep -v -e '^\s*#' -e '^\s*$' results.txt | awk '{if ($1=="DUPTYPE_FIRST_OCCURRENCE") printf("\n"); for (i=0; i<=NF; i++){if (i>7) printf("%s "),$i} printf("\n")}' > duplications.txt
cat duplications.txt | sed -e 's/^/#rm -v \"/' | sed -e 's/$/\"/' | sed -e 's/#rm -v \""//g' | sed 's/\ "$/\"/g' > rmfile_comout.sh
実行すると、コメントアウトされた膨大なrmコマンドのシェルスクリプトが作成される。そのうち、必要なもの以外のコメントアウトを除外すると重複が排除される。
ブロックの先頭の一個を除いて最初からコメントアウトしないとか、リストの長さに応じて出力をカスタマイズすると良い気がする。自分の場合、例えば下記のpythonスクリプトのようにキーワードで削除するファイルを選んだりしている。
import sys
# 下記のキーワードを含むパスのファイルを消去する場合
rmlist = []
rmlist.append('KEYWORD1')
rmlist.append('KEYWORD2')
rmlist.append('KEYWORD3')
# as well ...
# キーワードを含むパスのコメントアウトを外す
def process(lines):
nline = len(lines)
n = 0
for line in lines:
delete = False
token = line.strip()
for l in rmlist:
if l in token:
delete = True
if delete:
n = n + 1
if n < nline: # 同一ファイルのリストのうち最後の1個は残す
print(token.replace('#',''))
else:
print(token)
else:
print(token)
return 0
# 標準入力で処理する
lines = []
for line in sys.stdin:
if line != '\n':
lines.append(line)
elif line == '\n':
print("")
dummy = process(lines)
lines = []
最後の行にパイプで繋いでも良いし、
cat rmfile_comout.sh | python3.x selection.py > rmfile.sh
として結果を確認しつつ調整しても良い。そのうち残すファイルを明示的に選びたいシチュエーションも出てくるかもしれない。