sed

sed

我有大约 700 个文件夹。每个文件夹都包含文件的成对组合。我想为每个成对组合只保留一个文件。任何成对文件都可以保留,因为它们都包含相同的内容。文件夹中的文件不一定按字母顺序命名。

  Example: 
      Folder1: 
        -> A-B.txt
        -> B-A.txt

      Folder2: 
        -> C-D.txt
        -> C-E.txt
        -> E-C.txt
        -> D-E.txt
        -> D-C.txt
        -> E-D.txt

     Final folder structure: 
         Folder1: 
               -> A-B.txt (or) B-A.txt
         Folder2: 
               -> C-D.txt (or) D-C.txt
               -> C-E.txt (or) E-C.txt
               -> D-E.txt (or) E-D.txt

答案1

你可以做类似的事情

  ls *.txt | awk -F '[.-]' '{ if (f[$2,$1]) { print $0; }
                              else { f[$1,$2] = 1} }' | xargs rm

其工作原理如下:将相关文件的名称提供给awk.对于每个文件,检查数组中是否已输入具有相反名称的文件f。如果是,则输出文件名。如果没有,则放入数组中f。使用程序的输出awk删除重复的文件。

答案2

您可以使用find并提取文件名中破折号之前和之后的部分,测试该对是否存在,如果存在则删除相应的文件:

find . -name \*-\*.txt -execdir sh -c 'fn=${1##*/};bn=${fn%.*};one=${bn%-*};
two=${bn#*-};pair=${two}-${one}.txt; [[ -f $pair ]] && rm "$1"' boom {} \;

可以使用循环完成同样的操作for(假设 shell 支持递归通配符):

# if you're using bash run
shopt -s globstar

然后

for f in **/*-*.txt; do
dn=${f%/*}; fn=${f##*/}; bn=${fn%.*}; one=${bn%-*}; two=${bn#*-};
pair=${dn}/${two}-${one}.txt; [[ -f $pair ]] && rm -- "$f"; done

答案3

find . -type d -exec \
   perl -wMstrict -le '
      (local $", my $top) = ("", $ENV{PWD});
      for my $curdir ( @ARGV ) {
         my %h;
         chdir $curdir;
            for ( <*.txt> ) {
               my @pair = /^([^-]+)-([^.]+)[.]txt$/;
               next unless @pair;
               $h{ "@pair" }++;
               unlink if exists $h{ "@{[reverse @pair]}" };
            }
         chdir $top;
      }
   ' {} +

sed

/bin/ls -1 |
sed -ne '
   1H;1d
   G
   /^\([^-]*\)-\([^.]*\).txt\n\(.*\n\)\{0,1\}\2-\1.txt$/P
   /^\([^-]*\)-\([^.]*\).txt\n\(.*\n\)\{0,1\}\2-\1.txt\n/P
   s/\n\n.*//;H
' | xargs rm

相关内容