Viime aikoina minun on poistettava paljon kaksoiskappaleita. Yhdistän kolme tai neljä tiedostojärjestelmää ja haluan, että tilaa käytetään taloudellisesti. Aluksi fdupes
näytti siltä, että se oli paras työkalu työhön, mutta minulla on yhä enemmän rajoituksia.
Harkitse komentoa fdupes -rdN somedirectory/
. Tämä tekee hajautuksen kaikista tiedostoista jonkin hakemiston alihakemistoissa.
Ja kun se havaitsee kaksoiskappaleita, se poistaa ne, joten kaikesta on vain yksi kopio.
Mutta entä jos haluan säilyttää somedirectory/subdirectory1/somefile
ja itse asiassa on neljä kaksoiskappaletta, ja ohjelma kohtaa ensin yhden kaksoiskappaleista? Sitten se poistaa somedirectory/subdirectory1/somefile
, jota en halua.
Haluan pystyä jotenkin määrittelemään, mitkä kopiot säilytetään. Ja toistaiseksi mikään kaksoiskappaleiden käsittelyyn tarkoitettujen vakio-ohjelmien (duff, FSLint) näyttävät mahdollistavan tällaisen käyttäytymisen automatisoinnin. En haluaisi, että en tekisi omaa, joten siksi kysyn tämän kysymyksen.
Haluaisin pystyä kirjoittamaan jotain sellaista:
killdupes -rdN --keep=filesin,somedirectories,separated,by,commas somedirectory/
Kommentit
- Olin etsimässä samaa ja löysin tämän superuser.com/a/561207/218922
vastauksen
Vaikka etsimääsi toimintoa ei ole varastossa fdupes
, haarauin fdupes
(haarukkaa kutsutaan nimellä jdupes
) ja lisättiin joitain ominaisuuksia, jotka voivat ratkaista tämän ongelman tietyissä olosuhteissa. esimerkki ilmoitetussa tapauksessa, jossa haluat säilyttää somedirectory/subdirectory1/somefile
kun kaksoiskappaleet poistetaan automaattisesti (d
ja N
kytketään yhteen), eikä somedirectory
, jdupes
voidaan syöttää jokaiselle välittömälle alihakemistopolulle subdirectory1
ensin ja -O
-kytkin (joka lajittelee tiedostot ensin komentoriviparametrijärjestyksessä):
jdupes -nrdNO somedirectory/subdirectory1 somedirectory/subdirectory2 somedirectory/subdirectory3
Tämä poistaa automaattisesti kaikki paitsi yhden tiedoston kaksoiskopiosta ja takaa, että jos sarja sisältää tiedoston somedirectory/subdirectory1
, se on ensimmäinen, jolloin siitä tulee automaattisesti ryhmän säilytetty tiedosto . Tällä lähestymistavalla on edelleen räikeitä rajoja, kuten se, että toinen kopio somedirectory/subdirectory1
-palvelussa voidaan säilyttää sen sijaan, että halusit säilyttää, mutta monissa tapauksissa sinun kaltaisissasi tapauksissa jdupes
-parametritilausvaihtoehto kiertotapana on tarpeeksi hyvä.
Aion lisätä lähitulevaisuudessa suodatusjärjestelmän kohtaan jdupes
joka mahdollistaa valtavan määrän hallintaa tiedostojen sisällyttämisessä / poissulkemisessa, -N
-toimintojen säilyttämisessä ja tällaisten ”suodatinpinoiden” soveltamisessa joko maailmanlaajuisesti tai per -parametri. Tätä ominaisuutta tarvitaan kipeästi; Kuvittelen jotain tällaista ”poistaa nollasta poikkeavat kaksoiskappaleet rekursiivisesti, mutta säilytä aina somedirectory/subdirectory1/somefile
sellaisena kuin se on”:
jdupes -nrdN --filter=preserve:somedirectory/subdirectory1/somefile somedirectory/
Vastaa
En nähnyt tätä missään muualla: Sano mitä haluat. / mnt / folder-tree-1 / mnt / folder-tree-2. Et halua poistaa kaikkia dupe-tiedostoja, mutta jos puu-2: ssa on tiedosto ja puu-1: ssä on identtinen tiedosto, täsmälleen sama polku ja nimi, poista se puusta 2.
Varoitus: tämä on melko lyhyt, ja jos yrität kopioida-liittää tämän rajoitetuilla kuoritaidoilla, ole varovainen.
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
Tai kaikki yhdellä rivillä:
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
Tarkasta ja suorita jälkeenpäin rm-v2-dupes.sh
vastaus
Entä kaksoiskappaleiden sitominen yhteen? Tällä tavalla tilaa käytetään vain kerran, mutta niitä on edelleen kaikilla poluilla. Tämän takana on, että kovakytkettyjä tiedostoja tulisi muuttaa paikalleen (niitä tulisi muokata vain poistamalla tiedosto ja luomalla se uudella sisällöllä). Toinen tapa on linkittää tiedostot yhteen, vaikka sinulla on sama asia päättää, mikä ”ensisijainen” tiedosto on. Tämä voidaan tehdä seuraavalla komentosarjalla (vaikka huomaa, että tämä ei käsittele välilyöntejä sisältäviä tiedostonimiä).
fdupes --quiet --recurse --sameline somedirectory/ | while read SOURCE DESTS; do for DEST in $DESTS; do ln -f $SOURCE $DEST done done
Kommentit
-
jdupes
: n käyttäminenfdupes
voit yksinkertaisesti siirtyäjdupes -nrL somedirectory/
, joka on huomattavasti nopeampi. - Kirjoitusvirhe jdupes-linkissä. Mukavuuslinkki: github.com/jbruchon/jdupes
vastaus
Minulla oli sama kysymys.Jos sinulla on useita kaksoiskappaleita, fdupes /my/directory/ -rdN
pitää tiedoston, jolla on vanhin muokkauspäivä, tai jos useilla tiedostoilla on sama muokkauspäivämäärä, sitten ensimmäinen löytyi.
Jos muokkauspäivä ei ole sinulle tärkeä, voit touch
säilyttää haluamasi hakemiston tiedostot. Jos valitset touch
heille nykyisen päivämäärän ja kellonajan, fdupes -rdNi
säilyttää nykyisen päivämäärän. Tai voit touch
säilyttää tiedostot, joiden päivämäärä on aikaisempi kuin poistettavien tiedostojen päivämäärä, ja käyttää fdupes -rdN
normaalisti.
Jos sinun on pidettävä muokkauspäivämäärä, sinun on käytettävä jotain muuta tapaa.
Vastaa
Vain lisätä kierre edelliseen vastaukseen. Olen käyttänyt seuraavaa koodia useita kertoja, muokkaamalla hieman edellistä vastausta yksinkertaisella | grep
-toiminnolla poistettavan kansion eristämiseksi.
`fdupes -r -n -S /directory | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh`
Jälleen tämä luo sh-tiedoston kaikkien luettelossa olevien tiedostojen poistamiseksi, ei kommentoituja rivejä. Voit tietysti edelleen muokata tiedostoa kommentoidaksesi tiettyjä rivejä / tiedostoja, jotka haluat säilyttää.
Toinen vihje suurille hakemistoille on ajaa fdupes txt-tiedostoon ja kokeilla sitten | grep
ja | sed
, kunnes saan haluamasi tulos.
`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`
Vastaa
Käytä sed
luodaksesi komentotiedoston, joka sisältää kommentoidut komennot kaikkien päällekkäiset tiedostot:
fdupes -r -n -S /directory | sed -r "s/^/#rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh
Tuloksena oleva remove-duplicate-files.sh
tiedosto Juuri luomamme kukin rivi kommentoidaan. Kommentoi poistettavia tiedostoja. Suorita sitten sh remove-duplicate-files.sh
. Voila!
PÄIVITYS
No, jos et halua poistaa tiedostoja vain tietyistä hakemistoista, se on niin yksinkertaista kuin tämä :
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
Missä exclude_duplicates.py
on:
#/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)
Tuloksena saatu remove-duplicate-files-keep-protected.sh
tiedosto, jonka olemme juuri luoneet, kommentoi kaikkia suojattujen hakemistojen tiedostoja. Avaa tämä tiedosto suosikkitekstieditorissasi, tarkista, että kaikki on kunnossa. Suorita sitten. Voila (sic)!
Kommentit
- ajattelin tätä, mutta se ’ ei ole tarpeeksi automatisoitu. Tyhmästi aiheutin tietojen menetystä tällä menetelmällä, kun useiden tiedostojärjestelmien toisistaan toisistaan poikkeavien kopioiden käsitteleminen … ’ ei ole mitään tapaa antaa prioriteettia fdup-lähdön perusteella es. pohjimmiltaan minun olisi pitänyt troolata 10000 tiedostoa käsin tietojen menetyksen estämiseksi … joten ei kiitos … itse asiassa, että tietojen menetys on juuri syy, miksi esitin tämän kysymyksen.
- @ixtmixilix, no, manuaalinen menetelmä riippuu käyttäjän tarkkaavaisuudesta, tässä ’ ei ole mitään uutta. Jos haluat jotain automatisoitua, maksa päivitetty vastaus yllä.
Vastaa
Entä tällainen?
#!/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
vastaus
Apple File Filesystem (APFS) -versio on pitää tiedostot, kopioida ne, eikä sillä ole vaikutusta levyn käyttöön. Katso Korvaa APFS: n olemassa olevat kaksoiskappaleet klooneilla