V poslední době musím smazat spoustu duplikátů. Sloučím tři nebo čtyři souborové systémy a chci, aby byl prostor využit ekonomicky. Zpočátku se fdupes zdálo, že je to nejlepší nástroj pro danou práci, ale stále více narážím na omezení.

Zvažte příkaz fdupes -rdN somedirectory/. Tím se vytvoří hash všech souborů v podadresářích nějakého adresáře.

A když narazí na duplikáty, odstraní je, takže je k dispozici pouze jedna kopie všeho.

Ale co když si chci ponechat somedirectory/subdirectory1/somefile a ve skutečnosti existují čtyři duplikáty a program nejprve narazí na jeden z duplikátů? Pak odstraní somedirectory/subdirectory1/somefile, které nechci.

Chci být schopen určit, jaké duplikáty zachovat. A zatím žádný Zdá se, že standardní programy pro práci s duplikáty (duff, FSLint) umožňují automatizaci tohoto druhu chování. Raději nebudu házet svým vlastním, proto se ptám na tuto otázku.

Rád bych mohl psát něco jako

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

Komentáře

odpověď

I když hledaná funkce není na skladě k dispozici fdupes, rozdvojil jsem fdupes (moje vidlice se jmenuje jdupes) a přidal několik funkcí, které za určitých okolností mohou tento problém vyřešit. příklad v uvedeném případě, kdy si chcete ponechat somedirectory/subdirectory1/somefile při automatickém mazání duplikátů (d a N se přepíná) a pod somedirectory, jdupes lze každou cestu podadresáře napájet jako první subdirectory1 a -O přepínač (který nejprve seřadí soubory podle pořadí parametrů příkazového řádku):

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

Toto automaticky smaže všechny soubory kromě jednoho v duplicitní sadě a zaručí, že pokud sada obsahuje soubor v somedirectory/subdirectory1, bude to první, čímž se automaticky stane zachovaným souborem v sadě . Stále existují do očí bijící limity tohoto přístupu, například skutečnost, že může být zachován jiný duplikát v somedirectory/subdirectory1 místo toho, který jste si chtěli ponechat, ale v mnoha případech, jako je váš, jdupes možnost pořadí parametrů jako alternativní řešení je dostatečně dobrá.

V blízké budoucnosti plánuji přidat do které umožní obrovské množství kontroly nad zahrnutím / vyloučením souborů, uchováním -N akcí a aplikací těchto „filtrů“ na globální nebo na -parametrický základ. Tato funkce je velmi nutná; Představuji si něco takového pro „automatické mazání nenulových duplikátů rekurzivně, ALE vždy zachovat somedirectory/subdirectory1/somefile tak, jak je“:

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

Odpověď

Neviděl jsem to nikde jinde: Řekněte, co chcete, toto. Máte / mnt / folder-tree-1 / mnt / folder-tree-2. Nechcete odstranit všechny dupe, ale pokud existuje soubor ve stromu-2 a stejný soubor existuje ve stromu-1 s přesně stejným cesta a název, odstraňte jej ze stromu-2.

Varování: je to docela stručné a pokud se pokusíte kopírovat a vložit toto s omezenými znalostmi prostředí, buďte opatrní.

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 

Nebo vše na jednom řádku:

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 

Poté zkontrolujte a proveďte rm-v2-dupes.sh

Odpověď

Co takhle pevné propojení duplicitních souborů? Tímto způsobem je prostor použit pouze jednou, ale stále existují ve všech cestách. Háček v tom je, že soubory s pevným odkazem by měly být upraveny na místě (měly by být upraveny pouze odstraněním souboru a jeho opětovným vytvořením s novým obsahem). Druhým přístupem je symbolické propojení souborů dohromady, i když máte stejný problém s rozhodováním o tom, který „primární“ soubor je. To lze provést pomocí následujícího skriptu (i když si uvědomte, že to nezpracovává názvy souborů obsahující mezery).

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

Komentáře

  • Použití jdupes namísto fdupes můžete jednoduše přejít jdupes -nrL somedirectory/, což je výrazně rychlejší.
  • Překlep v odkazu na jdupes. Odkaz na pohodlí: github.com/jbruchon/jdupes

Odpověď

Měl jsem stejnou otázku.Pokud máte mnoho duplikátů, fdupes /my/directory/ -rdN uchová soubor s nejstarším datem úpravy, nebo pokud má několik souborů stejné datum úpravy, bude ten nalezen jako první.

Pokud pro vás datum úpravy není důležité, můžete touch soubory v adresáři, který si chcete ponechat. Pokud je zvolíte touch s aktuálním datem a časem, fdupes -rdNi zachová ty s aktuálním datem. Nebo můžete touch uchovat soubory s datem dřívějším než ty, které chcete smazat, a použít fdupes -rdN jako obvykle.

Pokud si chcete ponechat datum úpravy, budete muset použít některou z dalších metod.

Odpovědět

Stačí přidat twist k předchozí odpovědi. Následující kód jsem použil několikrát, přičemž jsem mírně upravil předchozí odpověď jednoduchým | grep k izolaci složky, ze které chci smazat.

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

Opět se vytvoří soubor sh, který odstraní všechny uvedené soubory, žádné řádky bez komentářů. Samozřejmě stále můžete soubor upravit tak, aby komentoval konkrétní řádky / soubory, které si chcete ponechat.

Další radou pro velké adresáře je spustit fdupes do souboru txt a poté experimentovat s | grep a | sed, dokud nedostanu výsledek chci.

`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` 

odpověď

Pomocí sed vytvořte soubor prostředí, který bude obsahovat komentované příkazy k odstranění každého z vašich duplicitní soubory:

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

Výsledný remove-duplicate-files.sh fil To, co jsme právě vytvořili, bude mít každý řádek komentovaný. Odkomentujte soubory, které chcete smazat. Poté spusťte sh remove-duplicate-files.sh . Voila!

AKTUALIZACE

Pokud nechcete mazat soubory pouze v určitých adresářích, je to tak jednoduché :

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 

Kde exclude_duplicates.py je:

 #/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)  

Výsledný remove-duplicate-files-keep-protected.sh , který jsme právě vytvořili, bude mít všechny soubory z chráněných adresářů komentovány. Otevřete tento soubor ve svém oblíbeném textovém editoru, zkontrolujte, zda je vše v pořádku. Potom jej spusťte. Voila (sic)!

Komentáře

  • myslel jsem na to, ale ‚ to není dostatečně automatizované. Hloupě, touto metodou jsem způsobil ztrátu dat, když zacházení s duplikáty rozmístěnými napříč více souborovými systémy … neexistuje ‚ způsob přiřazení priority vzhledem k výstupu fdup es. v zásadě bych musel ručně procházet 10 000 souborů, abych zabránil této ztrátě dat … takže žádné poděkování … ve skutečnosti je právě tato ztráta dat důvodem, proč jsem položil tuto otázku.
  • @ixtmixilix, manuální metoda závisí na pozornosti uživatele, zde ‚ není nic nového. Pokud chcete něco automatizovanějšího, podívejte se na aktualizovanou odpověď výše.

Odpověď

A co něco takového?

#!/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 

Odpověď

Od Apple Filesystem (APFS), dalšího řešení je uchovat soubory, deduplikovat je a mít žádný vliv na použití disku. Viz Nahradit existující duplicitní soubory na APFS klony

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *