首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有条件删除重复文件

有条件删除重复文件
EN

Unix & Linux用户
提问于 2019-06-11 22:07:27
回答 3查看 1.1K关注 0票数 1

只有当文件同名时,我才想删除重复的文件。比如:rdfind -deleteduplicates true ~/folder无法实现我的目标。

一种方法是获得一个试运行的rdfind的输出(results.txt),

代码语言:javascript
复制
rdfind -n true "$PWD"

并确定每个组的第一个文件的名称相同,以:DUPTYPE_FIRST_OCCURRENCE XXXX开头标识。

代码语言:javascript
复制
DUPTYPE_FIRST_OCCURRENCE 5148 2 37934240 2054 16916792 1 /home/fig3.tif
DUPTYPE_WITHIN_SAME_TREE -5148 3 37934240 2054 17044654 1 /home/other/fig3.tif
DUPTYPE_WITHIN_SAME_TREE -5148 3 35435435 2054 16546546 1 /home/other2/fig3.tif

DUPTYPE_FIRST_OCCURRENCE 5160 2 116397930 2054 16916804 1 /home/file.psd
DUPTYPE_WITHIN_SAME_TREE -5160 2 116397930 2054 16916870 1 /home/folder/file.psd
DUPTYPE_WITHIN_SAME_TREE -5160 2 116397930 2054 17654654 1 /home/folder/file2.psd

在上面的示例中,对于第1组2重复项,应该删除第2组中的重复项,而在第2组中,只有一个重复项应该被删除,其名称与第一次事件(file.psd)相同。

编辑:对于rmlint的答案是可取的。使用兰林特通常可以建立“原始”文件。

EN

回答 3

Unix & Linux用户

发布于 2020-04-21 20:12:05

此脚本将对从results.txt生成的rdfind文件进行后处理,如您的问题所示:

代码语言:javascript
复制
#!/bin/bash
#
while read -r type x x x x x x path
do
    case "$type" in

        DUPTYPE_FIRST_OCCURRENCE)
            name="${path##*/}"
            echo "New path for $name" >&2
            ;;

        DUPTYPE_WITHIN_SAME_TREE|DUPTYPE_OUTSIDE_TREE)
            if [[ -n "$name" ]] && [[ ${path##*/} == $name ]]
            then
                echo "Remove duplicate $path" >&2
                # rm -f "$path"
            else
                echo "Skipping differently named $path" >&2
            fi
            ;;
    esac
done

当您准备好让rm完成它的工作时,取消它的注释。如果不需要详细的内容,请注释掉echo语句(或重定向stderr)。

循环顶部的read -r type x x x x x x path语句读取八个空格分隔的字段。中间的六个不相关,所以我将它们读入一个垃圾变量中,然后丢弃;只使用$type$path

生成results.txt

代码语言:javascript
复制
rdfind -dryrun true -makeresultsfile true {directory...}

对生成的文件进行后处理(rddedup是我的脚本,如上所示)

代码语言:javascript
复制
rddedup < results.txt
票数 3
EN

Unix & Linux用户

发布于 2020-04-22 18:50:56

怎么换种方法剥这只猫的皮?(OP编辑请求rmlint是在我即将发布这篇文章的时候做的,不过没关系,不如把这个.参见编辑在底部re rmlint) )

由于结构已知,在删除空行之前,文件名的第一个出现是目标文件名和随后的重复文件名,那么我们也可以使用awk,尽管可能比@roaima慢一些。

代码语言:javascript
复制
awk 'NF==0{getline; target=""}
     target==""{l=split($8,t,"/"); target=t[l];getline}
     {l=split($8,q,"/");if (q[l]==target)print $8}' file1 | while read f; do echo rm $f ; done

演练

如果有空行,跳过它并将目标文件名重置为""

代码语言:javascript
复制
awk 'NF==0{getline; target=""}

如果目标未设置(即在每一行空白行之后开始),则从这一行获取目标文件名,然后跳到下一行。

代码语言:javascript
复制
     target==""{l=split($8,t,"/"); target=t[l];getline}

现在,根据目标检查当前行中的文件名,如果匹配,则输出完整路径。

代码语言:javascript
复制
     {l=split($8,q,"/");if (q[l]==target)print $8}' file1

然后通过循环管道awk来执行实际的删除(只需删除echo)。

代码语言:javascript
复制
    | while read f; do echo rm $f ; done

尽管您也可以这样做(同样,只需删除echo)

代码语言:javascript
复制
     {l=split($8,q,"/");if (q[l]==target)print $8}' file1 | xargs echo rm

编辑rmlint前面,你似乎很难控制原创性的优先级

默认情况下,如果在rmlint命令中指定多个路径,则第一个命名路径中的文件将被视为比后一个命名路径更“原始”的文件。如果同一路径中有两个文件,则旧文件将被视为原始文件。如果他们有相同的修改时间,那么这只是一个偶然的问题,其中一个被选为原始。

但是对于您的显式示例,-d选项(原始是文件层次结构中最低的)将与-b结合使用,以根据文件名而不是内容进行匹配。

代码语言:javascript
复制
rmlint -d -b /home/

诚然,这比我的脚本要短得多,但是阅读rmlint页面比编写脚本花费的时间更长。选你所选。

顺便说一句,未经测试.

票数 1
EN

Unix & Linux用户

发布于 2020-04-23 17:11:03

以下是roaima的脚本,用于处理副本之间的对应关系,而不是给定文件列表中的第一个。例如:同一个文件有三个名称:a/xb/yc/y。然后,当a/x是基本文件(DUPTYPE_FIRST_OCCURRENCE)时,其他文件之一将被删除。

代码语言:javascript
复制
#!/bin/bash

while read -r type x x x x x x path
do
    name="${path##*/}"
    [[ "$type" == '#' ]] || [[ -z "$name" ]] && 
        printf "%s\n" "skipping a non-entry looking line">&2
    case "$type" in
        DUPTYPE_FIRST_OCCURRENCE)
            printf "New path for %s: %s\n" "$name" "$path">&2
            unset ass
            declare -A ass
            ass["$name"]=1
            ;;

        DUPTYPE_WITHIN_SAME_TREE|DUPTYPE_OUTSIDE_TREE)
            if [ "${ass["$name"]}"x != "x" ]
            then
                printf "Remove duplicate: %s\n" "$path" >&2
                # rm -f "$path"
            else
                ass["$name"]=1
                printf "Skipping differently named file: %s\n" "$path" >&2
            fi
            ;;
    esac 
done < results.txt

还包括了一些其他的更改,这些更改应该是可读的,不需要注释。ass是一个关联数组。

我必须承认,这个脚本还没有经过很好的测试,所以可能还会有一些问题有待解决。

Example使用。 rdfind -n true .,然后我们有以下内容:

代码语言:javascript
复制
$ ls *
results.txt  script.bash

a:
filea0  filea1  fileb0

b:
filea1  fileb0

c:
fileb0

results.txt:

代码语言:javascript
复制
$ cat results.txt 
# Automatically generated
# duptype id depth size device inode priority name
DUPTYPE_FIRST_OCCURRENCE 4 1 6 64773 4849814 3 ./a/filea0
DUPTYPE_WITHIN_SAME_TREE -4 1 6 64773 4849816 3 ./b/filea1
DUPTYPE_WITHIN_SAME_TREE -4 1 6 64773 4849817 3 ./a/filea1
DUPTYPE_FIRST_OCCURRENCE 6 1 6 64773 4849677 3 ./a/fileb0
DUPTYPE_WITHIN_SAME_TREE -6 1 6 64773 4849819 3 ./b/fileb0
DUPTYPE_WITHIN_SAME_TREE -6 1 6 64773 4986586 3 ./c/fileb0
# end of file

在行动中的脚本:

代码语言:javascript
复制
./script.bash
skipping a non-entry looking line
skipping a non-entry looking line
New path for filea0: ./a/filea0
Skipping differently named file: %s\n ./b/filea1
Remove duplicate: ./a/filea1
New path for fileb0: ./a/fileb0
Remove duplicate: ./b/fileb0
Remove duplicate: ./c/fileb0
skipping a non-entry looking line
票数 1
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/524310

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档