fdupes -rdNより洗練された複製を削除する方法はありますか?


22

最近、多くの重複を削除する必要があります。3つまたは4つのファイルシステムをマージしていますが、そのスペースを経済的に使用したいです。最初fdupesは仕事に最適なツールのように見えましたが、次第に制限に直面しています。

コマンドを検討してくださいfdupes -rdN somedirectory/。これにより、somedirectoryのサブディレクトリ内のすべてのファイルのハッシュが作成されます。

そして、重複が見つかるとそれらを削除するため、すべてのコピーが1つだけになります。

しかし、保持somedirectory/subdirectory1/somefileしたいのですが、実際には4つの重複があり、プログラムが最初に重複の1つに遭遇した場合はどうなりますか?次に、を削除しますがsomedirectory/subdirectory1/somefile、これは望ましくありません。

どういうわけか、保持する複製を指定できるようにしたいと思います。そしてこれまでのところ、重複を処理するための標準プログラム(duff、FSLint)は、そのような動作の自動化を許可していないようです。私は自分で転がしたくないので、この質問をしているのはそのためです。

私は次のようなものを書きたいです

killdupes -rdN --keep=filesin,somedirectories,separated,by,commas somedirectory/

私は同じものを探していて、このsuperuser.com/a/561207/218922
アレクシス

回答:


5

探している機能は在庫がありませんがfdupes、フォークしてfdupes (フォークはjdupes呼ばれ、特定の状況でこの問題を解決できる機能を追加しました。たとえば、somedirectory/subdirectory1/somefile重複を自動削除するときに保持しておきたい場合(dおよびNスイッチを一緒に切り替えます)、すぐ下somedirectoryに個別のファイルがない場合jdupessubdirectory1最初の-Oスイッチと各スイッチ(コマンドでファイルをソートする)行パラメーターの順序が最初):

jdupes -nrdNO somedirectory/subdirectory1 somedirectory/subdirectory2 somedirectory/subdirectory3

これにより、重複セット内の1つのファイルを除くすべてが自動的に削除され、セットにファイルが含まれている場合はそのファイルがsomedirectory/subdirectory1最初になり、セット内の保存ファイルに自動的になります。このアプローチsomedirectory/subdirectory1には、保持したいものの代わりに別の重複が保存される可能性があるなど、依然として大きな制限がありますが、あなたのような多くの場合jdupes、回避策としてのパラメータ順序オプションで十分です。

近い将来、jdupesファイルの包含/除外、-Nアクションの保存、およびこのような「フィルタースタック」の適用をグローバルまたはパラメーターごとに制御できるフィルタリングシステムを追加する予定です。この機能は非常に必要です。「ゼロ以外の重複を再帰的に自動削除しますが、常に現状を維持する」ために、次のようなものを想定していますsomedirectory/subdirectory1/somefile

jdupes -nrdN --filter=preserve:somedirectory/subdirectory1/somefile somedirectory/


4

重複ファイルをハードリンクすることはどうですか?そうすれば、スペースは一度しか使用されませんが、すべてのパスに存在します。これの難点は、ハードリンクされたファイルをその場で変更する必要があることです(ファイルを削除して新しいコンテンツで再作成するだけで変更する必要があります)。もう1つの方法は、ファイルをシンボリックリンクすることです。ただし、「プライマリ」ファイルを決定するという同じ問題があります。これは、次のスクリプトを使用して実行できます(ただし、スペースを含むファイル名は処理されないことに注意してください)。

fdupes --quiet --recurse --sameline somedirectory/ | while read SOURCE DESTS; do
    for DEST in $DESTS; do
        ln -f $SOURCE $DEST
    done
done

1
jdupes代わりに使用fdupesすることで、jdupes -nrL somedirectory/非常に高速な処理を実行できます。
ジョディリーブルション16

1
jdupesへのリンクのタイプミス。便利なリンク:github.com/jbruchon/jdupes
ロイスウィリアムズ

4

私はこれを他のどこにも見ませんでした:あなたが望むのはこれだと言います。/ mnt / folder-tree-1 / mnt / folder-tree-2があります。すべてのデュープを削除する必要はありませんが、ファイルがツリー2に存在し、ツリー1にまったく同じパスと名前を持つ同一のファイルが存在する場合、ツリー2から削除します。

警告:これは非常に簡潔で、限られたシェルスキルでこれをコピーアンドペーストしようとする場合は注意してください。

fdupes -rn /mnt/folder-tree-1/ /mnt/folder-tree-2/ > dupes-all.txt

fgrep /mnt/folder-tree-1/ dupes-all.txt | while read line
do
if grep -q "`echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|'`" dupes-all.txt
then
    echo rm \"$(echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2//|')\"
fi
done > rm-v2-dupes.sh

またはすべてを1行で:

fdupes -rn /mnt/folder-tree-1/ /mnt/folder-tree-2/ > dupes-all.txt; fgrep /mnt/folder-tree-1/ dupes-all.txt | while read line; do if grep -q "`echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|'`" dupes-all.txt; then echo rm \"$(echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|')\"; fi; done > rm-v2-dupes.sh

その後、rm-v2-dupes.shを調べて実行します


4

同じ質問がありました。重複が多い場合fdupes /my/directory/ -rdNは、ファイルの更新日が最も古いか、複数のファイルの更新日が同じである場合、最初に見つかったファイルが最初に見つかります。

変更日付が重要でない場合はtouch、保持するディレクトリ内のファイルを使用できます。touch現在の日付と時刻を選択すると、現在の日付と時刻 fdupes -rdNiのものが保持されます。またはtouch、削除しfdupes -rdNて通常どおり使用するファイルよりも古い日付のファイルを保持することもできます。

変更日を保持する必要がある場合は、他の方法のいずれかを使用する必要があります。


3

前の答えにひねりを加えるだけです。次のコードを複数回使用し、以前の回答を少し変更して、| grep削除したいフォルダーを簡単に分離しました。

`fdupes -r -n -S /directory | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh`

繰り返しますが、これにより、shファイルが作成され、リストされているすべてのファイルが削除され、コメント行は削除されません。もちろん、ファイルを編集して、保持したい特定の行/ファイルをコメントアウトすることもできます。

大規模なディレクトリのためのもう一つのヒントは、その後、txtファイルにfdupesを実行して実験することである| grep| sed私は私が望む結果を得るまで。

`fdupes -r -n -S /directory > duplicate-files.txt`
`cat duplicate-files.txt | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh`

2

sed重複ファイルのそれぞれを削除するためにコメントアウトされたコマンドを含むシェルファイルを作成するために使用します:

fdupes -r -n -S /directory | sed -r "s/^/#rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh

remove-duplicate-files.sh作成したばかりの結果ファイルには、各行がコメント化されています。削除するファイルのコメントを解除します。次にを実行しsh remove-duplicate-files.shます。出来上がり!

更新

特定のディレクトリ内のファイルのみを削除したくない場合は、次のように簡単です:

fdupes -S /directory|sed '/^$/d' |sed -r "s/^[0-9]/#&/" > duple_list

python exclude_duplicates.py -f /path/to/dupe_list --delimiter='#' --keep=/full/path/to/protected/directory1,/full/path/to/protected/directory2\ with\ spaces\ in\ path >remove-duplicate-files-keep-protected.sh

どこで exclude_duplicates.pyあります:

#/usr/bin/python
# -*- coding: utf-8 -*-
# exclude_duplicates.py
"""
THE SCRIPT DOESN'T DELETE ANYTHING, IT ONLY GENERATES TEXT OUTPUT.
Provided a list of duplicates, such as fdupes or fslint output,
generate a bash script that will have all duplicates in protected
directories commented out. If none of the protected duplicates are
found in a set of the same files, select a random unprotected
duplicate for preserving.
Each path to a file will be transformed to an `rm "path"` string which
will be printed to standard output.     
"""

from optparse import OptionParser
parser = OptionParser()
parser.add_option("-k", "--keep", dest="keep",
    help="""List of directories which you want to keep, separated by commas. \
        EXAMPLE: exclude_duplicates.py --keep /path/to/directory1,/path/to/directory\ with\ space\ in\ path2""",
    metavar="keep"
)
parser.add_option("-d", "--delimiter", dest="delimiter",
    help="Delimiter of duplicate file groups", metavar="delimiter"
)
parser.add_option("-f", "--file", dest="file",
    help="List of duplicate file groups, separated by delimiter, for example, fdupes or fslint output.", metavar="file"
)

(options, args) = parser.parse_args()
directories_to_keep = options.keep.split(',')
file = options.file
delimiter = options.delimiter

pretty_line = '\n#' + '-' * 35
print '#/bin/bash'
print '#I will protect files in these directories:\n'
for d in directories_to_keep:
    print '# ' + d
print pretty_line

protected_set = set()
group_set = set()

def clean_set(group_set, protected_set, delimiter_line):
    not_protected_set = group_set - protected_set
    while not_protected_set:
        if len(not_protected_set) == 1 and len(protected_set) == 0:
            print '#randomly selected duplicate to keep:\n#rm "%s"' % not_protected_set.pop().strip('\n')
        else:
            print 'rm "%s"' % not_protected_set.pop().strip('\n')
    for i in protected_set: print '#excluded file in protected directory:\n#rm "%s"' % i.strip('\n')
    print '\n#%s' % delimiter_line
file = open(file, 'r')
for line in file.readlines():
    if line.startswith(delimiter):
        clean_set(group_set, protected_set, line)
        group_set, protected_set = set(), set()
    else:
        group_set = group_set|{line}
        for d in directories_to_keep:
            if line.startswith(d): protected_set = protected_set|{line}
else:
    if line: clean_set(group_set, protected_set, line)

remove-duplicate-files-keep-protected.sh作成したばかりの結果ファイルには、保護されたディレクトリのすべてのファイルがコメント化されます。お気に入りのテキストエディタでこのファイルを開き、すべてが正常であることを確認します。次に実行します。出来上がり(sic)!


私はこれを考えましたが、十分に自動化されていません。愚かなことに、複数のファイルシステムにまたがる重複を処理するときに、この方法でデータが失われました... fdupesの出力を考えると、優先順位を割り当てる方法がありません。基本的に、データの損失を防ぐために10000個のファイルを手作業で探し回らなければならなかったので、実際には、データの損失がこの質問をしたまさにその理由です。
ixtmixilix

@ixtmixilix、まあ、手動の方法はユーザーの注意力に依存していますが、これは新しいものではありません。さらに自動化したい場合は、上記の更新された回答をご覧ください。
イヴァンハララモフ

2

このようなものはどうですか?

#!/bin/bash

DUPE_SEARCH_DIR=somedir/
PREFERRED_DIRS=("somedir/subdir1" "somedir/subdir2")
DUPE_FILE=/tmp/`basename $0`_found-duplicates

delete_dupes() {
    while read line ; do
        if [ -n "$line" ] ; then
            matched=false
            for pdir in "${PREFERRED_DIRS[@]}" ; do
                if [[ $line == $pdir/* ]] ; then
                    matched=true
                    break
                fi
            done
            if ! $matched ; then
                rm -v "$line"
            fi
        fi
    done < "$DUPE_FILE"
}

cleanup() {
    rm -f $DUPE_FILE
}

trap cleanup EXIT

# get rid of normal dupes, preserve first & preserve preferred
fdupes -rf "$DUPE_SEARCH_DIR" > $DUPE_FILE
delete_dupes

# get rid of preserve dupes, preserve preferred
fdupes -r "$DUPE_SEARCH_DIR" > "$DUPE_FILE"
delete_dupes
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.