对于目录中共享相同前缀的每组文件,删除除最近的 n 个文件之外的所有文件

sky*_*ork 5 bash shell-script timestamps files

我的问题与一些较旧的问题略有不同,这些问题只是要求“删除除最近的以外的所有内容” n目录中除文件外的文件。

我有一个包含不同“组”文件的目录,其中每组文件共享一些任意前缀,并且每组至少有一个文件。我事先不知道这些前缀,也不知道有多少组。

编辑:实际上,我对文件名有所了解,即它们都遵循模式prefix-some_digits-some_digits.tar.bz2。这里唯一重要的是prefix零件,我们可以假设在每个prefix都没有数字或破折号。

我想在bash脚本中执行以下操作:

  1. 浏览给定的目录,识别所有现有的“组”,对于每组文件,仅删除n该组中除最新文件之外的所有文件。

  2. 如果n某个组的文件少于该组,则对该组不执行任何操作,即不删除该组的任何文件。

在 中执行上述操作的稳健且安全的方法是什么bash?你能一步一步解释这些命令吗?

fer*_*rdy 3

剧本:

#!/bin/bash

# Get Prefixes

PREFIXES=$(ls | grep -Po '^(.*)(?!HT\d{4})-(.*)-(.*).tar.bz2$' | awk -F'-' '{print $1}' | uniq)

if [ -z "$1" ]; then
  echo need a number of keep files.
  exit 1
else
  NUMKEEP=$1
fi

for PREFIX in ${PREFIXES}; do

  ALL_FILES=$(ls -t ${PREFIX}*)

  if [ $(echo ${ALL_FILES} | wc -w) -lt $NUMKEEP ]; then
    echo Not enough files to be kept. Quit.
    continue
  fi

  KEEP=$(ls -t ${PREFIX}* | head -n${NUMKEEP})

  for file in $ALL_FILES ; do
    if [[ "$KEEP" =~ "$file" ]]; then
      echo keeping $file
    else
      echo RM $file
    fi
  done
done
Run Code Online (Sandbox Code Playgroud)

解释:

  • 计算前缀:
    • 查找正则something-something-something.tar.bz2表达式后面的所有文件,仅剪切第一部分到第一个破折号,并使其唯一。
    • 结果是标准化列表PREFIXES
  • 遍历所有PREFIXES
  • 计算ALL_FILESPREFIX
  • 检查数量是否ALL_FILES小于要保留的文件数 -> 如果为真,我们可以到此为止,无需删除任何内容
  • 计算KEEP最近的NUMKEEP文件
  • 遍历ALL_FILES并检查给定文件是否不在KEEP文件列表中。如果是这样:将其删除。

运行时的示例结果:

$ ./remove-old.sh 2
keeping bar-01-01.tar.bz2
keeping bar-01-02.tar.bz2
RM bar-01-03.tar.bz2
RM bar-01-04.tar.bz2
RM bar-01-05.tar.bz2
RM bar-01-06.tar.bz2
keeping foo-01-06.tar.bz2
keeping foo-01-05.tar.bz2
RM foo-01-04.tar.bz2
RM foo-01-03.tar.bz2
RM foo-01-02.tar.bz2

$ ./remove-old.sh 8
Not enough files to be kept. Quit.
Not enough files to be kept. Quit.
Run Code Online (Sandbox Code Playgroud)