删除多个文件夹中的重复文件

时间:2014-09-12 03:42:16

标签: linux shell directory-structure

我有一个目录,其中包含许多子目录和子子目录等等。我想选择一个特定的文件夹说A并删除A以外的目录中的所有文件,如果这些文件同时出现在AA以外的目录中。基本上我想通过保持A中的文件完整来删除重复(仅参考A)。此外,对于A中未出现的所有文件,我希望在任何一个目录中只保留一个副本(可能基于按字典顺序排列的第一个目录名或任何其他选择标准)。

请帮我写相同的剧本。

4 个答案:

答案 0 :(得分:1)

有关运行此脚本的示例,请参阅下面的用法注意:此脚本包含实际的删除文件已注释。要启用实际删除文件,您需要在脚本中取消注释# rm "$rmfn"

注2:要实际删除文件,您必须为此脚本提供3rd参数:-d以使文件被删除。如果您只提供参数1: A(要保存的文件的路径)和参数2: pathB(带子目录的路径以查找欺骗in),然后此脚本只打印找到的重复项,这样您就可以在执行删除之前验证所有内容。

Linux应用程序fdupes 我不应该告诉您,有一个共同的应用程序fdupes旨在完成您想要做的事情(很多更加灵活和彻底的测试)。

#!/bin/bash

## check input dirs both exist
[ -e "$1" ] && [ -e "$2" ] || {
    printf "\nError: invalid path. Usage %s dirA pathB\n\n" "${0##*/}"
    exit 1
}

tmp="tmp_$(date +%s).txt"               # unique temp file name
[ -f "$tmp" ] && rm "$tmp"              # test if already exists and del
find "$2" -type f > "$tmp"              # fill tmp file with possible dups

for i in $(find "$1" -type f); do       # check each file in A ($1) against tmp
    fn="${i##*/}"                       # remove path from A/filename
    if grep -q "$fn" "$tmp"; then       # test if A/file found in pathB ($2)
        if [ "$3" = -d ]; then          # if 3rd arg is '-d', really delete
            for rmfn in $(grep "$fn" "$tmp"); do        # get list of matching filenames
                printf " deleting: %s\n" "$rmfn" >&2    # print record of file deleted 
                # rm "$rmfn"            # the delete command (commented)
            done
        else                            # if no '-d', just print duplicates found
            printf "\n  Duplicate(s) found for: %s\n\n" "$fn"
            grep "$fn" "$tmp"           # output duplicate files found
        fi
    fi
done

rm "$tmp"                               # delete tmp file

exit 0

<强>用法:

脚本需要2个目录作为输入来扫描重复项需要第三个参数&#39; -d&#39; 实际删除找到的重复项。示例:

$ bash fdupes.sh ~/scr/utl ~/scr/rmtmp/

  Duplicate found for: bay.sh

/home/david/scr/rmtmp/bay.sh

  Duplicate found for: rsthemes.sh

/home/david/scr/rmtmp/rsthemes.sh

  Duplicate found for: nocomment

/home/david/scr/rmtmp/nocomment.sh

  Duplicate found for: show-rdtcli.sh

/home/david/scr/rmtmp/show-rdtcli.sh
/home/david/scr/rmtmp/subdir1/show-rdtcli.sh
<snip>

实际删除重复项(取消注释rm后):

$ bash fdupes.sh ~/scr/utl ~/scr/rmtmp/ -d

 deleting: /home/david/scr/rmtmp/bay.sh
 deleting: /home/david/scr/rmtmp/rsthemes.sh
 deleting: /home/david/scr/rmtmp/nocomment.sh
 deleting: /home/david/scr/rmtmp/show-rdtcli.sh
 deleting: /home/david/scr/rmtmp/subdir1/show-rdtcli.sh

答案 1 :(得分:0)

C#:     使用System.IO;

string filePathA =.... //get file path in folder A
string filePathB =.... //get file path in folder B
string fileNameA = filePathA.Replace(Server.MapPath("~/ImagesA/"), "");
string fileNameB = filePathA.Replace(Server.MapPath("~/ImagesB/"), "");

if(fileNameA.ToString() == fileNameB.ToString())
    File.Delete(filePathB);

答案 2 :(得分:0)

在Shell脚本中,您可以执行以下操作:

for f in origin/* ; do rm final/*$(basename $f) ; done

简单,完成工作。 对于第二部分,您可以进行嵌套迭代,比较所有文件以确保它们是唯一的。

for o in origin/* ; do
    for f in final/* ; do
        if [$(basename $f) -eq $(basename $o)] ; then
            rm $f
        else # if the file is not in A, but you want to check if its unique

            # do a new iteration
            for d in final/* ; do

                # if the file name is equal but they are not the same file, delete de second. 
                if [$(basename $f) -eq $(basename $d)] ; then
                    if [$f -ne $d] ; then
                        rm $d
                    fi
                fi                            
        fi

done

答案 3 :(得分:0)

尝试以下代码。这将创建一个带有Cyrillic sum的文件,按cksum值排序文件内容,而不是迭代文件列表并删除重复文件。

find . -type f -exec cksum {}  \; > cksum.txt
cat cksum.txt |sort -n > filelist

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