Answers:
#!/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
这既是递归的,也可以处理任何文件名。缺点是需要使用4.x版才能使用关联数组和递归搜索。echo
如果您喜欢结果,请删除。
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='"' *
请注意,这仍然会破坏名称中带有双引号的文件。没有真正的方法可以解决这个问题awk
。echo
如果您喜欢结果,请删除。
echo cksm
在开头的行后添加一个read
。
**
,它会以以下方式对列表进行排序:两个文件夹是交错的,而不是文件夹1的全部然后是文件夹2的全部。脚本将始终保留第一个“原始”文件夹遍历列表时命中。您可以echo $file
在该read
行之前查看是否为真。
fdupes是您选择的工具。要在当前目录中查找所有重复文件(按内容而不是名称):
fdupes -r .
要手动确认删除重复文件:
fdupes -r -d .
要自动删除除每个重复文件的第一个文件外的所有副本(请注意,此警告实际上会根据请求删除文件):
fdupes -r -f . | grep -v '^$' | xargs rm -v
建议删除之前手动检查文件:
fdupes -rf . | grep -v '^$' > files
... # check files
xargs -a files rm -v
-d '\n'
fdupes -rdN .
其中-r是递归的,-d是删除,-N是无提示
有点懒,很快我就在网上找到了一个。
首先,您必须为每个文件创建一个CRC校验和,因为您显然只想删除精确的重复项。
cksum *.jpg | sort -n > filelist
然后,遍历此文件列表,读取校验和以及文件名。如果两个校验和相同,则文件将被删除。这是可行的,因为排序是数字形式的,并且仅对校验和进行排序,校验和将重复文件分组。
old=""
while read sum lines filename
do
if [[ "$sum" != "$old" ]] ; then
old="$sum"
continue
fi
rm -f "$filename"
done < filelist
显然,这不是递归的。
如何测试具有唯一内容的文件?
if diff "$file1" "$file2" > /dev/null; then
...
我们如何获取目录中的文件列表?
files="$( find ${files_dir} -type f )"
我们可以从该列表中获取任意2个文件,并检查它们的名称是否不同以及内容是否相同。
#!/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
例如,我们有一些目录:
$> ls .tmp -1
all(2).txt
all.txt
file
text
text(2)
因此,只有3个唯一文件。
让我们运行该脚本:
$> ./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'
而且我们只剩下3个文件。
$> ls .tmp/ -1
all.txt
file
text(2)
我写了这个小脚本来删除重复的文件
https://gist.github.com/crodas/d16a16c2474602ad725b
基本上,它使用一个临时文件(/tmp/list.txt
)创建文件及其哈希表。后来,我使用该文件和Unix管道的魔力来完成其余的工作。
该脚本不会删除任何内容,但是会打印命令以删除文件。
mfilter.sh ./dir | bash
希望能帮助到你
删除重复文件的更简洁版本(仅一行)
young@ubuntu-16:~/test$ md5sum `find ./ -type f` | sort -k1 | uniq -w32 -d | xargs rm -fv
#!/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
我发现了执行相同任务的简便方法
for i in `md5sum * | sort -k1 | uniq -w32 -d|awk '{print $2}'`; do
rm -rf $i
done
这不是您要的内容,但我认为当校验和不相同但名称相似(括号中带有后缀)时,有人会发现它很有用。该脚本删除后缀为(“数字”)的文件
#! /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