क्या fdupes -rdN की तुलना में अधिक परिष्कृत डुप्लिकेट को हटाने का एक तरीका है?


22

हाल ही में मुझे बहुत सारे डुप्लिकेट को हटाने की आवश्यकता है। मैं तीन या चार फाइल सिस्टम का विलय कर रहा हूं, और मैं चाहता हूं कि अंतरिक्ष का आर्थिक रूप से उपयोग किया जाए। पहले, fdupesऐसा लगता था कि यह नौकरी के लिए सबसे अच्छा उपकरण था, लेकिन मैं तेजी से सीमाओं में भाग रहा हूं।

कमांड पर विचार करें fdupes -rdN somedirectory/। यह किसी न किसी प्रकार की सभी फ़ाइलों की हैश को किसी न किसी प्रकार की उपनिर्देशिका में बनाता है।

और जब यह डुप्लिकेट का सामना करता है, तो यह उन्हें हटा देता है, ताकि हर चीज की एक ही प्रति हो।

लेकिन क्या होगा अगर मैं रखना चाहता हूं somedirectory/subdirectory1/somefileऔर वास्तव में, चार डुप्लिकेट हैं, और प्रोग्राम पहले डुप्लिकेट में से एक का सामना करता है? फिर इसे हटा दिया जाता है somedirectory/subdirectory1/somefile, जो मुझे नहीं चाहिए।

मैं किसी तरह निर्दिष्ट करने में सक्षम होना चाहता हूं, जो रखने के लिए डुप्लिकेट करता है। और अब तक, डुप्लिकेट्स (डफ, एफएसलिंट) से निपटने के लिए कोई भी मानक कार्यक्रम उस तरह के व्यवहार के स्वचालन की अनुमति नहीं देता है। मैं अपना रोल नहीं करना चाहूंगा, इसलिए मैं यह सवाल पूछ रहा हूं।

मैं कुछ लिखने में सक्षम होना चाहता हूं

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

मैं एक ही चीज़ की तलाश में था और मुझे यह सुपरसुअर.com
561207

जवाबों:


5

जब आप चाहते हैं कि कार्यक्षमता स्टॉक में उपलब्ध नहीं है fdupes, तो मैंने कांटा fdupes (मेरा कांटा कहा जाता है jdupes) और कुछ विशेषताओं को जोड़ा जो इस समस्या को कुछ परिस्थितियों में हल कर सकते हैं। उदाहरण के लिए, बताए गए मामले में, जहां आप रखना चाहते हैं somedirectory/subdirectory1/somefileजब ऑटो-डुप्लिकेट ( dऔर Nएक साथ स्विच) को हटाते हैं और तुरंत नीचे कोई अलग फाइलें नहीं होती हैं somedirectory, पहले और स्विच के jdupesसाथ प्रत्येक तत्काल उपनिर्देशिका पथ को खिलाया जा सकता है (जो कमांड द्वारा फ़ाइलों को सॉर्ट करता है -लाइन पैरामीटर ऑर्डर पहले):subdirectory1-O

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

यह डुप्लिकेट सेट में सभी एक-एक फ़ाइल को ऑटो-डिलीट कर देगा और यह गारंटी देगा कि यदि सेट में कोई फ़ाइल है, तो somedirectory/subdirectory1यह पहला होगा, जिससे स्वचालित रूप से सेट में संरक्षित फ़ाइल बन जाएगी। इस दृष्टिकोण की अभी भी कुछ सीमाएँ हैं जैसे कि एक और डुप्लिकेट somedirectory/subdirectory1जिसे आप रखना चाहते थे, उसके बजाय संरक्षित किया जा सकता है, लेकिन आपके जैसे कई मामलों में, jdupesवर्कअराउंड के रूप में पैरामीटर ऑर्डर विकल्प काफी अच्छा है।

निकट भविष्य में, मैं एक फ़िल्टरिंग सिस्टम जोड़ने की योजना बना रहा हूं, jdupesजो फ़ाइलों के समावेश / बहिष्करण, -Nक्रियाओं के लिए संरक्षण , और वैश्विक या प्रति-पैरामीटर आधार पर ऐसे "फ़िल्टर स्टैक" के अनुप्रयोग पर भारी मात्रा में नियंत्रण सक्षम करेगा । इस सुविधा की आवश्यकता है; मैं कुछ इस तरह की कल्पना करता हूं "ऑटो-डिलीट नॉन-जीरो डुप्लिकेट्स को रीसर्वली ब्यूट हमेशा प्रोटेक्टेड-एज़ somedirectory/subdirectory1/somefile":

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


4

डुप्लिकेट फ़ाइलों को एक साथ हार्डलिंक करने के बारे में क्या? इस तरह से अंतरिक्ष केवल एक बार उपयोग किया जाता है, लेकिन वे अभी भी सभी रास्तों में मौजूद हैं। इसके साथ पकड़ यह है कि हार्डलिंक की गई फ़ाइलों को जगह में संशोधित किया जाना चाहिए (उन्हें केवल फाइल को हटाने और नई सामग्री के साथ इसे फिर से संशोधित करना चाहिए)। अन्य दृष्टिकोण फ़ाइलों को एक साथ समेटना है, हालांकि आपके पास यह निर्णय लेने का एक ही मुद्दा है कि "प्राथमिक" फ़ाइल क्या है। यह निम्नलिखित स्क्रिप्ट के साथ किया जा सकता है (हालांकि ध्यान दें कि यह रिक्त स्थान वाले फ़ाइलनाम को नहीं संभालता है)।

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/जो बड़े पैमाने पर जल्दी है।
जोड़ी ली ब्रूचोन

1
Jdupes के लिंक में टाइपो। सुविधा लिंक: github.com/jbruchon/jdupes
रॉयस विलियम्स

4

मैंने इसे कहीं और नहीं देखा: कहो कि तुम क्या चाहते हो। आपके पास / mnt / folder-tree-1 / mnt / folder-tree-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

या सभी एक लाइन पर:

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`

फिर से, यह सूचीबद्ध सभी फ़ाइलों को हटाने के लिए एक श फाइल बनाएगा, कोई टिप्पणी नहीं की गई लाइनें। बेशक आप अभी भी फ़ाइल को संपादित करने के लिए विशिष्ट लाइनों / फ़ाइलों को टिप्पणी कर सकते हैं जिन्हें आप रखना चाहते हैं।

बड़ी निर्देशिकाओं के लिए एक और संकेत एक 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.