Nemrégiben sok másolat törlésére van szükségem. Három vagy négy fájlrendszert egyesítek, és azt akarom, hogy a helyet gazdaságosan használják. Eleinte úgy tűnt, hogy a fdupes
a legjobb eszköz a munkához, de egyre inkább korlátokba ütközök.
Vegye figyelembe a . Ez kivonatolja az összes fájlt a valamilyen könyvtár alkönyvtáraiban.
És amikor ismétlődésekkel találkozik, törli őket, így mindenből csak egy példány van.
De mi van, ha meg akarok tartani somedirectory/subdirectory1/somefile
és valójában négy példány létezik, és a program először találkozik az egyik duplikátummal? Ezután törli a somedirectory/subdirectory1/somefile
fájlt, amelyet nem akarok.
Szeretném valahogy megadni, hogy melyik másolatot kell megtartani. És egyelőre sem úgy tűnik, hogy a másolatok kezelésére szolgáló szokásos programok (duff, FSLint) lehetővé teszik az ilyen viselkedés automatizálását. Inkább nem szeretném a sajátomat forgatni, ezért “teszem fel ezt a kérdést.
Szeretnék ilyet írni:
killdupes -rdN --keep=filesin,somedirectories,separated,by,commas somedirectory/
Megjegyzések
- ugyanazt keresem, és megtaláltam ezt az superuser.com/a/561207/218922
választ
Bár a keresett funkció nem áll rendelkezésre fdupes
, én elágaztam fdupes
(a villám neve: jdupes
) , és hozzáadott néhány olyan funkciót, amelyek bizonyos körülmények között megoldják ezt a problémát. például abban az esetben, ha meg akarja tartani a a duplikátumok automatikus törlésénél (a d
és a N
kapcsolók együtt kapcsolnak), és a somedirectory
, jdupes
minden közvetlen alkönyvtár-útvonalat előbb subdirectory1
és a -O
kapcsoló (amely először fájlokat rendez a parancssori paraméterek sorrendje szerint):
jdupes -nrdNO somedirectory/subdirectory1 somedirectory/subdirectory2 somedirectory/subdirectory3
Ez automatikusan törli az összes fájlt egy kivételével egy duplikátumkészletben, és garantálja, hogy ha a halmaz tartalmaz egy fájlt a somedirectory/subdirectory1
fájlban, akkor ez lesz az első, és ezáltal automatikusan a készlet megőrzött fájljává válik . Ennek a megközelítésnek még mindig vannak kirívó korlátai, például az a tény, hogy a somedirectory/subdirectory1
fájlban meg lehet őrizni egy másik másolatot a megtartani kívánt helyett, de nagyon sok esetben, mint a tiéd, A jdupes
paraméter sorrend opciója megoldásként elég jó.
A közeljövőben egy szűrőrendszert tervezek hozzáadni a amely lehetővé teszi a fájlok beillesztésének / kizárásának hatalmas ellenőrzését, a -N
műveletek megőrzését és az ilyen “szűrőkészletek” alkalmazását globális vagy külön-külön. -paraméter alapon. Erre a funkcióra nagyon szükség van; Valami ilyesmit úgy képzelem el, hogy “a nullától eltérő duplikátumok automatikus törlése rekurzív módon, DE mindig megőrizze a somedirectory/subdirectory1/somefile
állapotot:
jdupes -nrdN --filter=preserve:somedirectory/subdirectory1/somefile somedirectory/
Válasz
Nem láttam ezt sehol máshol: Mondd, amit akarsz. / mnt / folder-tree-1 / mnt / folder-tree-2. Nem akarsz minden dupe-ot eltávolítani, de ha egy fájl létezik a fa-2-ben, és egy azonos fájl létezik a tree-1-ben, pontosan ugyanazokkal elérési út és név, távolítsa el a fa-2-ből.
Figyelmeztetés: ez elég szűkszavú, és ha korlátozott shell-készséggel próbálja ezt másolni-beilleszteni, legyen óvatos.
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
Vagy mindez egy sorban:
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
Utána ellenőrizze és hajtsa végre az rm-v2-dupes.sh
Válasz
Mi van a duplikált fájlok összekapcsolásával? Így a teret csak egyszer használják, de még mindig léteznek az összes ösvényen. Az a fogás, hogy a merevhivatkozású fájlokat a helyükön módosítani kell (azokat csak a fájl törlésével és az új tartalommal való újrateremtéssel lehet módosítani). A másik megközelítés a fájlok összekapcsolása, bár ugyanaz a kérdés, hogy eldöntse, melyik az „elsődleges” fájl. Ez megtehető a következő szkript segítségével (bár vegye figyelembe, hogy ez nem kezeli a szóközöket tartalmazó fájlneveket).
fdupes --quiet --recurse --sameline somedirectory/ | while read SOURCE DESTS; do for DEST in $DESTS; do ln -f $SOURCE $DEST done done
Megjegyzések
- A
jdupes
használatafdupes
helyett egyszerűen elmehetjdupes -nrL somedirectory/
, amely jelentősen gyorsabb. - Gépelési hiba a jdupes linkjében. Kényelmi link: github.com/jbruchon/jdupes
Válasz
Ugyanaz a kérdésem volt.Ha sok másolat van, akkor fdupes /my/directory/ -rdN
a legrégebbi módosítási dátumot tartja meg, vagy ha több fájlnak ugyanaz a módosítási dátuma, akkor az elsőnek talált.
Ha a módosítás dátuma nem fontos az Ön számára, touch
fájlokat tárolhat a megtartani kívánt könyvtárban. Ha úgy dönt, hogy touch
az aktuális dátummal és idővel, akkor a fdupes -rdNi
megtartja az aktuális dátumot. Vagy touch
megtarthatja a törölni kívánt fájloknál korábbi dátumú fájlokat, és a szokásos módon használhatja a fdupes -rdN
fájlt.
Ha meg kell őriznie a módosítás dátumát, akkor a többi módszer egyikét kell használnia.
Válasz
Csak egy csavar hozzáadása az előző válaszhoz. A következő kódot többször is felhasználtam, egy korábbi | grep
egyszerű változtatással módosítva a korábbi választ, hogy elkülönítsem a törölni kívánt mappát.
`fdupes -r -n -S /directory | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh`
Ismételten létrehoz egy sh fájlt az összes felsorolt fájl törléséhez, megjegyzés nélküli sorok nélkül. Természetesen továbbra is szerkesztheti a fájlt, hogy megjegyezze azokat a sorokat / fájlokat, amelyeket meg akar tartani.
A nagy könyvtárak másik tippje az, hogy az fdupes fájlokat futtatja egy txt fájlba, majd kísérletezzen a | grep
és | sed
elemekkel, amíg meg nem kapom a kívánt eredményt.
`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`
Válasz
A sed
használatával hozzon létre egy shell fájlt, amely kommentált parancsokat tartalmaz az egyes fájlok törléséhez. duplikált fájlok:
fdupes -r -n -S /directory | sed -r "s/^/#rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh
Az eredményül kapott remove-duplicate-files.sh
fájl Az imént létrehozott sorok mindegyikét kommentálják. Kommentálja a törölni kívánt fájlokat. Ezután futtassa az sh remove-duplicate-files.sh
parancsot. Voálá!
UPDATE
Nos, ha csak bizonyos könyvtárakban akarsz fájlokat törölni, akkor ez ilyen egyszerű :
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
Hol van 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)
Az eredményül kapott remove-duplicate-files-keep-protected.sh
fájlban a védett könyvtárak összes fájlját megjegyzik. Nyissa meg ezt a fájlt a kedvenc szövegszerkesztőben, ellenőrizze, hogy minden rendben van-e. Ezután futtassa. Voila (sic)!
Megjegyzések
- gondoltam erre, de ez ‘ nem elég automatizált. Bután, ezzel a módszerrel adatvesztést okoztam, amikor több fájlrendszer között elhelyezett duplikátumok kezelése … ‘ nincs mód prioritás hozzárendelésére, tekintettel az fdup kimenetére es. alapvetően 10000 fájlt kellett volna kézzel vonszolnom, hogy megakadályozzam ezt az adatvesztést … szóval, köszönöm … valójában ez az adatvesztés az oka annak, hogy feltettem ezt a kérdést.
- @ixtmixilix, nos, a manuális módszer a felhasználó figyelmességétől függ, itt ‘ nincs semmi újdonság. Ha valami automatizáltabb dolgot szeretne, akkor nézzen meg egy frissített választ fent.
Válasz
Mi a helyzet ilyesmivel?
#!/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
Válasz
Az Apple Filesystem (APFS) óta egy másik megoldás a fájlok megőrzése, deduplikálása, és nincs hatással a lemez használatára. Lásd: Az APFS meglévő duplikált fájljainak cseréje klónokkal