根据日期删除重复的文件名

根据日期删除重复的文件名

我有数千个类似这样的文件。

  • wrfout_d03_2010-06-11_00:00:01
  • wrfout_d03_2010-06-11_00:00:08
  • wrfout_d03_2010-06-12_00:00:20
  • wrfout_d03_2010-06-12_00:00:35
  • wrfout_d03_2010-06-12_00:00:40

我只需要保留第一个时间戳。在这种情况下,

  • wrfout_d03_2010-06-11_00:00:01
  • wrfout_d03_2010-06-12_00:00:20

我可以知道这样做而不需要一一删除吗?谢谢!

答案1

zsh

typeset -A seen=()
for f (wrfout_d*(N)) (( seen[\${f%_*}]++ )) && echo rm -f $f

echo(如果对结果满意则删除)

等效bash的(假设 bash 4.0 或更高版本)如下所示:

(shopt -s nullglob
typeset -A seen=()
for f in wrfout_d*; do
   (( seen[\${f%_*}]++ )) && echo rm -f "$f"
done)

全局扩展按词法排序,因此使用时间戳格式,这确实与时间顺序一致。因此,上面我们从最旧到最年轻的顺序遍历文件,如果已经看到删除了最短尾随_*( ) 的名称(如关联数组中记录的那样),则删除该文件。有关算术表达式中的原因,请参阅${f%_*}$seen A\如何在算术表达式中安全地使用关联数组?

答案2

prev=
for file in wrfout_d*_*_*; do
  head=${file%_*}
  if [ "$head" = "$prev" ]; then
    # Remove "echo" if output is correct
    echo rm -f -- "$file"
  else
    prev=$head
  fi
done

文件名最后一个下划线之前的部分被视为变量head。当与 相同的字符串echo rm时达到,否则设置为 的值。headprevprevhead

答案3

无可否认,使用 bash 数组的脆弱解决方案:

#!/bin/bash

workdir='/home/haxiel/testdir'
prefixes=( $(ls $workdir | cut -d '_' -f 1-3 | sort | uniq) )

for prefix in ${prefixes[@]}; do
files=( $workdir/$prefix* )
unset files[0]
echo rm -- ${files[@]}
done

我正在使用ls|cut|sort|uniq管道构建唯一前缀列表。

然后我循环遍历前缀并使用 shell 通配来获取与特定前缀匹配的所有文件并将其存储在数组中。您想保留第一个文件,因此我从数组中删除该文件并将其余文件传递给命令rm

此解决方案假设您的文件名不包含特殊字符。它还假设 shell 的排序顺序与您预期的排序顺序相匹配。

请务必将脚本放在工作目录之外。否则,脚本名称将被捕获为前缀之一。

运行一次并检查输出以确保您删除了正确的文件。然后,删除前面的'echo'命令rm并再次运行它。

与往常一样,数据删除是一个有风险的过程,因此请谨慎使用,并在您认为需要时进行备份。

相关内容