如何删除除文件的两个实例之外的所有实例?

时间:2014-06-12 20:10:54

标签: bash

我有一个带有类似命名文件的目录,在这种模式中:

00002_930831_fa.ppm  00398_940422_fa.ppm  00714_960530_fa.ppm
00002_930831_fb.ppm  00398_940422_fb.ppm  00714_960530_fb.ppm
00002_931230_fa.ppm  00399_940422_fa.ppm  00714_960620_fa.ppm
00002_931230_fb.ppm  00399_940422_fb.ppm  00714_960620_fb.ppm
00002_940128_fa.ppm  00400_940422_fa.ppm  00715_941201_fa.ppm
00002_940128_fb.ppm  00400_940422_fb.ppm  00715_941201_fb.ppm
00002_940422_fa.ppm  00401_940422_fa.ppm  00715_941205_fa.ppm
00002_940422_fb.ppm  00401_940422_fb.ppm  00715_941205_fb.ppm
00002_940928_fa.ppm  00402_940422_fa.ppm  00716_941201_fa.ppm
00002_940928_fb.ppm  00402_940422_fb.ppm  00716_941201_fb.ppm

我需要做的是删除例如除00002样本的两个实例之外的所有实例(并不重要),以便我以00002_930831_fa.ppm和{{为例离开1}}。问题是我需要为所有样本,00003,00004等完成此操作。我需要为每个样本留下两个文件。

我已经尝试00002_930831_fb.ppm,但我不确定如何解决我的病情。

这可以通过简单的管道命令来解决,还是我必须用bash脚本来解决它?

4 个答案:

答案 0 :(得分:3)

只需使用headtail过滤您的文件名列表:

ls 00002_* | tail -n +3 | xargs rm

答案 1 :(得分:2)

创建一个包含所有匹配文件名的数组,然后使用substring参数扩展运算符将前两个元素作为参数传递给rm

while read -r sample; do
  matching_files=( ${sample}_* )
  # To make sure at least two files survive:
  (( ${#matching_files[@]} > 2 )) && rm "${matching_files[@]:2}"
done < samples.txt

答案 2 :(得分:1)

使用关联数组:

#!/bin/bash

[[ BASH_VERSINFO -ge 4 ]] || {
    echo "You need Bash 4.0 or newer to run this script." >&2
    exit 1
}

declare -A COUNTER=()

for A in *.ppm; do
    IFS=_ read I __ <<< "$A"
    (( ++COUNTER[$I] > 2 )) && rm "$A" 
done

模拟:

Skip 00002_930831_fa.ppm
Skip 00002_930831_fb.ppm
rm 00002_931230_fa.ppm
rm 00002_931230_fb.ppm
rm 00002_940128_fa.ppm
rm 00002_940128_fb.ppm
rm 00002_940422_fa.ppm
rm 00002_940422_fb.ppm
rm 00002_940928_fa.ppm
rm 00002_940928_fb.ppm
Skip 00398_940422_fa.ppm
Skip 00398_940422_fb.ppm
Skip 00399_940422_fa.ppm
Skip 00399_940422_fb.ppm
Skip 00400_940422_fa.ppm
Skip 00400_940422_fb.ppm
Skip 00401_940422_fa.ppm
Skip 00401_940422_fb.ppm
Skip 00402_940422_fa.ppm
Skip 00402_940422_fb.ppm
Skip 00714_960530_fa.ppm
Skip 00714_960530_fb.ppm
rm 00714_960620_fa.ppm
rm 00714_960620_fb.ppm
Skip 00715_941201_fa.ppm
Skip 00715_941201_fb.ppm
rm 00715_941205_fa.ppm
rm 00715_941205_fb.ppm
Skip 00716_941201_fa.ppm
Skip 00716_941201_fb.ppm

注意:首先在一些虚拟文件上测试它。

来想一想:

IFS=_ read I __ <<< "$A"

可以

I=${A%%_*}

答案 3 :(得分:0)

使用bash版本4:

declare -A files
for f in *ppm; do
    files[${f%%_*}]+="$f "
done
for i in "${!files[@]}"; do
    set -- ${files[$i]}
    shift 2
    (($# > 0)) && echo rm $*
done

如果您对选择要删除的正确文件感到满意,请删除echo

如果有任何带有空格的文件名,则无效。