最近、多くの重複を削除する必要があります。 3つまたは4つのファイルシステムをマージしていて、スペースを経済的に使用したいと考えています。最初は、fdupes
がこの仕事に最適なツールのように見えましたが、ますます制限に直面しています。
コマンド。これにより、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
回答を見つけました
お探しの機能は在庫がありませんfdupes
、私はfdupes
(私のフォークはjdupes
と呼ばれます)そして特定の状況下でこの問題を解決できるいくつかの機能を追加しました。たとえば、重複を自動削除し(d
とN
が一緒に切り替わる)、
、jdupes
には、最初にsubdirectory1
を最初に-O
スイッチ(最初にコマンドラインパラメータの順序でファイルを並べ替えます):
jdupes -nrdNO somedirectory/subdirectory1 somedirectory/subdirectory2 somedirectory/subdirectory3
これ重複するセット内の1つを除くすべてのファイルを自動削除し、セットにsomedirectory/subdirectory1
のファイルが含まれている場合、それが最初になることを保証します。これにより、自動的にセット内の保存ファイルになります。 。 somedirectory/subdirectory1
の別の複製が、保持したいものの代わりに保持される可能性があるなど、このアプローチには依然として明白な制限がありますが、あなたのような多くの場合、回避策として、jdupes
パラメータの順序オプションで十分です。
近い将来、これにより、ファイルの包含/除外、-N
アクションの保存、およびグローバルまたはごとのそのような「フィルタースタック」の適用を大幅に制御できます。 -パラメータベース。この機能は切実に必要です。 「ゼロ以外の重複を再帰的に自動削除しますが、常にsomedirectory/subdirectory1/somefile
をそのまま保持する」というようなものを想定しています:
jdupes -nrdN --filter=preserve:somedirectory/subdirectory1/somefile somedirectory/
回答
これは他のどこにも見当たりませんでした:これが欲しいと言ってください。 / mnt / folder-tree-1 / mnt / folder-tree-2。すべての重複を削除する必要はありませんが、ファイルがtree-2に存在し、まったく同じファイルがtree-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を検査して実行します
回答
重複ファイルを一緒にハードリンクするのはどうですか?そうすれば、スペースは1回だけ使用されますが、すべてのパスに存在します。これの欠点は、ハードリンクされたファイルをその場で変更する必要があることです(ファイルを削除して新しいコンテンツで再作成する場合にのみ変更する必要があります)。もう1つのアプローチは、ファイルをシンボリックリンクすることですが、「プライマリ」ファイルを決定するという同じ問題があります。これは、次のスクリプトで実行できます(ただし、これはスペースを含むファイル名を処理しないことに注意してください)。
fdupes --quiet --recurse --sameline somedirectory/ | while read SOURCE DESTS; do for DEST in $DESTS; do ln -f $SOURCE $DEST done done
コメント
-
fdupes
の代わりにjdupes
を使用するjdupes -nrL somedirectory/
に移動するだけで非常に高速になります。 - jdupesへのリンクを入力してください。便利なリンク: github.com/jbruchon/jdupes
回答
同じ質問がありました。重複が多数ある場合、fdupes /my/directory/ -rdN
はファイルを最も古い変更日で保持します。または、複数のファイルの変更日が同じである場合は、最初に見つかったファイルを保持します。
変更日が重要でない場合は、保持するディレクトリ内のファイルをtouch
できます。現在の日付と時刻でtouch
を選択した場合、fdupes -rdNi
は現在の日付でそれらを保持します。または、削除する日付より前の日付のファイルをtouch
保持し、通常どおりfdupes -rdN
を使用することもできます。
変更日を保持する必要がある場合は、他の方法のいずれかを使用する必要があります。
回答
前の答えにひねりを加えるだけです。次のコードを複数回使用し、以前の回答を単純な| grep
で少し変更して、削除するフォルダーを分離しました。
`fdupes -r -n -S /directory | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh`
ここでも、shファイルを作成して、リストされているすべてのファイルを削除します。コメント行はありません。もちろん、ファイルを編集して、保持したい特定の行/ファイルをコメントアウトすることもできます。
大きなディレクトリのもう1つのヒントは、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`
回答
sed
を使用して、コメントアウトされた各コマンドを削除するコマンドを含むシェルファイルを作成します。重複ファイル:
fdupes -r -n -S /directory | sed -r "s/^/#rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh
結果の remove-duplicate-files.sh
ファイル作成したばかりのeには、各行がコメントアウトされます。削除するファイルのコメントを解除します。次に、 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
ファイルには、保護されたディレクトリのすべてのファイルがコメントアウトされます。このファイルをお気に入りのテキストエディタで開き、すべて問題がないことを確認してから実行します。出来上がり(原文のまま)!
コメント
- これについて考えましたが、’が十分に自動化されていません。愚かなことに、この方法でデータが失われたのは複数のファイルシステムにまたがる重複を処理しています… ‘ fdupの出力を考えると、優先順位を割り当てる方法はありません。 es。基本的に、データの損失を防ぐために、10000個のファイルを手動でトロールする必要がありました…したがって、感謝しません…実際、データの損失がこの質問をした理由です。
- @ixtmixilix、まあ、手動の方法はユーザーの注意力に依存します。ここでは’新しいことは何もありません。より自動化されたものが必要な場合は、上記の更新された回答を確認してください。
回答
このようなものはどうですか?
#!/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
回答
Apple Filesystem(APFS)の時点で、別のソリューションファイルを保持し、重複排除し、ディスクの使用に影響を与えないようにすることです。 APFS上の既存の重複ファイルをクローンに置き換える
を参照してください。