Bir dizindeki kopyalanan dosyalar nasıl kaldırılır?


25

Bir dizine çok fazla resim indirdim.
Downloader önceden var olan dosyaları yeniden adlandırdı.
Ayrıca bazı dosyaları el ile yeniden adlandırdım.

a.jpg
b.jpg
b(2).jpg
hello.jpg      <-- manually renamed `b(3).jpg`
c.jpg
c(2).jpg
world.jpg      <-- manually renamed `d.jpg`
d(2).jpg
d(3).jpg

Çoğaltılanları nasıl kaldırılır? Sonuç şöyle olmalı:

a.jpg
b.jpg
c.jpg
world.jpg

not: isim önemli değil. Sadece uniq dosyaları istiyorum.

Yanıtlar:


27

bash 4.x

#!/bin/bash
declare -A arr
shopt -s globstar

for file in **; do
  [[ -f "$file" ]] || continue

  read cksm _ < <(md5sum "$file")
  if ((arr[$cksm]++)); then 
    echo "rm $file"
  fi
done

Bu hem özyinelemelidir hem de herhangi bir dosya adını işler. Dezavantajı, ilişkisel dizileri kullanma ve özyinelemeli arama özelliğini kullanabilmek için sürüm 4.x gerektirmesidir. echoSonuçları beğenirseniz kaldırın .

gawk versiyonu

gawk '
  {
    cmd="md5sum " q FILENAME q
    cmd | getline cksm
    close(cmd)
    sub(/ .*$/,"",cksm)
    if(a[cksm]++){
      cmd="echo rm " q FILENAME q
      system(cmd)
      close(cmd)
    }
    nextfile
  }' q='"' *

Bunun, adlarında çift tırnak bulunan dosyalara zarar vereceğini unutmayın. Bununla aşmanın gerçek bir yolu yok awk. echoSonuçları beğenirseniz kaldırın .


Tamam, bash sürümü benim için çalıştı, ancak benim denememde, 2 benzer klasörle, bir klasördeki çiftlerin yarısını ve diğerinin yarısını sildi. niye ya. Bir klasördeki herkesin (çoğaltılmış) silinmesini beklerdim.
Ferroao

@ Ferroao Belki de tam kopyaları değildi. Eğer sadece bir bit kapalıysa, betiğimin kopyaları belirlemek için kullandığı md5 karması tamamen farklı olacaktır. Her dosyanın karmasını görmek istiyorsanız, echo cksmile başlayan satırdan hemen sonra ekleyebilirsiniz read.
SiegeX

hayır, tüm "kopyalar" (kopyalar) kaldırıldı, 1 sürüm kaldı, diyelim. yarısı kopya bir klasörden, diğer yarısı diğer klasörden silinmiştir (kopyaların% 100'ü silinmiştir). %
100'üm

@ Ferroao görüyorum. Bu durumda bash özyinelemeli yolunu genişlettiğinde **, listeyi, iki klasörün tümünü önce tüm klasörler 1'den önce, sonra tüm klasörler 2'nin arasına girecek şekilde sıralar. Listede ilerledikçe çarptı. Bunun doğru olup olmadığını görmek echo $fileiçin readsatırdan önce yapabilirsiniz .
SiegeX

45

fdupes seçtiğiniz bir araçtır. Geçerli dizindeki tüm çift dosyaları (içeriğe göre, ada göre değil) bulmak için:

fdupes -r .

Kopyalanan dosyaların silinmesini manuel olarak onaylamak için:

fdupes -r -d .

Kopyalanan her dosyanın birincisi dışındaki tüm kopyaları otomatik olarak silmek için ( uyarılmalıdır, bu uyarı, bu aslında dosyaları istendiği gibi siler ):

fdupes -r -f . | grep -v '^$' | xargs rm -v

Silmeden önce dosyaları manuel olarak kontrol etmenizi tavsiye ederim:

fdupes -rf . | grep -v '^$' > files
... # check files
xargs -a files rm -v

Harika çalışıyor, ancak dosya adları boşluk içeriyorsa başarısız olur.
Daniel Wolf,

1
@DanielWolf xargs seçeneği ile deneyin-d '\n'
Jakob

1
Ayrıca, daha yeni fdup sürümleri, yinelenen dosyalar listesindeki ilki hariç hepsini silmek için yerleşik seçeneğe sahiptir: fdupes -rdN .burada -r özyinelemeli, -d silinir ve -N
Rand

Teşekkürler, Bu olağanüstü çünkü 2'den fazla kopya algılayabiliyor ve hangilerinin korumak istediğinizi (ya da hepsini) seçmenize izin veriyor.
Smeterlink


1

Biraz tembel olmak, çevrimiçi bir tane bulmak çok uzun sürmedi .

Öncelikle her bir dosya için bir CRC sağlama toplamı oluşturmalısınız, çünkü açıkça sadece tam kopyaları çıkarmak istediğinizde.

cksum  *.jpg | sort -n > filelist

Ardından, sağlama toplamı ve aynı zamanda dosya adını okuyarak bu dosya listesini yineleyin. İki sağlama toplamı aynıysa, dosya kaldırılır. Bu, sıralama sayısal olduğundan ve yalnızca yinelenen dosyaları gruplayan sağlama toplamlarına göre sıraladığından, çalışır.

old=""
while read sum lines filename
do
      if [[ "$sum" != "$old" ]] ; then
            old="$sum"
            continue
      fi
      rm -f "$filename"
done < filelist

Açıkçası, bu özyinelemeli çalışmıyor.


1

Eşsiz içeriğe sahip dosyalar nasıl test edilir?

if diff "$file1" "$file2" > /dev/null; then
    ...

Dizindeki dosyaların listesini nasıl alabiliriz?

files="$( find ${files_dir} -type f )"

Bu listeden 2 dosya alabilir ve adlarının farklı ve içeriğinin aynı olup olmadığını kontrol edebiliriz.

#!/bin/bash
# removeDuplicates.sh

files_dir=$1
if [[ -z "$files_dir" ]]; then
    echo "Error: files dir is undefined"
fi

files="$( find ${files_dir} -type f )"
for file1 in $files; do
    for file2 in $files; do
        # echo "checking $file1 and $file2"
        if [[ "$file1" != "$file2" && -e "$file1" && -e "$file2" ]]; then
            if diff "$file1" "$file2" > /dev/null; then
                echo "$file1 and $file2 are duplicates"
                rm -v "$file2"
            fi
        fi
    done
done

Örneğin, bazı dir:

$> ls .tmp -1
all(2).txt
all.txt
file
text
text(2)

Yani sadece 3 benzersiz dosya var.

Bu betiği çalıştıralım:

$> ./removeDuplicates.sh .tmp/
.tmp/text(2) and .tmp/text are duplicates
removed `.tmp/text'
.tmp/all.txt and .tmp/all(2).txt are duplicates
removed `.tmp/all(2).txt'

Ve sadece 3 dosya bıraktık.

$> ls .tmp/ -1
all.txt
file
text(2)

1

Kopyalanan dosyaları silmek için bu küçük betiği yazdım

https://gist.github.com/crodas/d16a16c2474602ad725b

Temel olarak /tmp/list.txt, dosyaların ve karmalarının haritasını oluşturmak için geçici bir dosya ( ) kullanır . Sonra bu dosyaları ve Unix borularının büyüsünü geri kalanını yapmak için kullanıyorum.

Betik hiçbir şeyi silmez, ancak dosyaları silmek için komutları yazdırır.

mfilter.sh ./dir | bash

Umarım yardımcı olur


1

Kopyalanan dosyaları kaldırmanın daha özlü versiyonu (sadece bir satır)

young@ubuntu-16:~/test$ md5sum `find ./ -type f` | sort -k1 | uniq -w32 -d | xargs rm -fv

find_same_size.sh

#!/usr/bin/env bash
#set -x
#This is small script can find same size of files.
find_same_size(){

if [[ -z $1 || ! -d $1 ]]
then
echo "Usage $0 directory_name" ;
 exit $?
else
dir_name=$1;
echo "current directory is $1"



for i in $(find $dir_name -type f); do
   ls -fl $i
done | awk '{f=""
        if(NF>9)for(i=9;i<=NF;i++)f=f?f" "$i:$i; else f=$9;
        if(a[$5]){ a[$5]=a[$5]"\n"f; b[$5]++;} else a[$5]=f} END{for(x     in b)print a[x] }' | xargs stat -c "%s  %n" #For just list files
 fi
   }

find_same_size $1


young@ubuntu-16:~/test$ bash find_same_size.sh tttt/ | awk '{ if($1 !~   /^([[:alpha:]])+/) print $2}' | xargs md5sum | uniq -w32 -d | xargs rm -vf

0

Aynı görevi yerine getirmenin daha kolay bir yolunu buldum

for i in `md5sum * | sort -k1 | uniq -w32 -d|awk '{print $2}'`; do
rm -rf $i
done

0

Kalan cevapların çoğu ve muhtemelen hepsi, işlenecek dizindeki her dosyanın sağlama toplamını hesaplayarak çok yetersizdir.

Potansiyel olarak daha hızlı bir yaklaşım yaklaşımı, ilk önce hemen hemen ( lsveya stat) hemen hemen olan ( veya ) hemen hemen her bir dosyanın boyutunu elde etmek ve daha sonra yalnızca benzersiz olmayan bir boyuta sahip dosyalar için sağlama toplamlarını hesaplamak ve karşılaştırmaktır.


0

İstediğiniz bu değil, ama sanırım sağlama toplamı aynı olmadığında birileri onu yararlı bulabilir, ancak isim benzer (parantez içinde sonek ile). Bu betik, ("digit") eklerine sahip dosyaları kaldırır.

#! /bin/bash
# Warning: globstar excludes hidden directories.
# Turn on recursive globbing (in this script) or exit if the option is not supported:
shopt -s globstar || exit
for f in **
do
extension="${f##*.}"
#get only files with parentheses suffix
FILEWITHPAR=$( echo "${f%.*}".$extension | grep -o -P "(.*\([0-9]\)\..*)")
# print file to be possibly deleted
if [ -z "$FILEWITHPAR" ] ;then
:
else
echo "$FILEWITHPAR ident"
# identify if a similar file without suffix exists
FILENOPAR=$(echo $FILEWITHPAR | sed -e 's/^\(.*\)([0-9])\(.*\).*/\1\2/')
echo "$FILENOPAR exists?"
if [ -f "$FILENOPAR" ]; then
#delete file with suffix in parentheses
echo ""$FILEWITHPAR" to be deleted"
rm -Rf "$FILEWITHPAR"
else
echo "no"
fi
fi
done

-3

Bu tür işleri gerçekten kolaylaştıran küçük bir program buldum: fdupes .


Lütfen kurulum talimatlarını ve soruya uygun bir kullanım örneği ekleyin.
simlev,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.