查找文件并从列表总数中删除 x

查找文件并从列表总数中删除 x

我想删除某个目录中的所有日志文件,但不是最新的 3 个。

我已经搞定了:

DATA_PATH=$(gadmin config get System.DataRoot)
ZK_PATH=${DATA_PATH}/zk/version-2

log_count=$(ls -ltrh ${ZK_PATH} | grep log | wc -l)
limit_files=`expr $log_count - 3`

echo There is ${log_count} files found in ${ZK_PATH}, ${limit_files} will be deleted, here the list:
ls -ltrh ${ZK_PATH} | grep log | head -${limit_files}

while true; do
    read -p "Are you sure to delete these files? " yn
    case $yn in
        [Yy1]* ) echo execute to delete the files; break;;
        [Nn0]* ) exit;;
        * ) echo "Please answer y or n.";;
    esac
done

如何删除列出的 12 个文件中的 9 个?

我考虑过首先将列表打印到文件中,然后使用循环将其一一删除,但我确信有代码可以仅用一行来完成此操作。

我尝试使用find ... -delete-exec、 和xargs rm,但无法正确使用它。

我该怎么做?

答案1

使用 zsh 而不是 bash,可以更轻松可靠地完成此类操作:

#! /bin/zsh -
data_path=$(gadmin config get System.DataRoot) || exit
zk_path=$data_path/zk/version-2
keep=3

files=( $zk_path/*log*(N.om) )

if (( $#files > keep )); then
  printf >&2 '%s\n' "$#files files found in $zk_path, $(( $#files - keep )) will be deleted, here is the list from newest to oldest:"
  shift keep files
  printf >&2 ' - "%s"\n' $files:t

  read -q '?OK to delete? ' && rm -f -- $files
fi

特别令人感兴趣的是$zk_path/*log*(N.om) 全局;它扩展到与*log*中的模式匹配的所有文件名$zk_path,并且括号(…)指定如果没有找到文件,则没有错误(Nullglob),我们只查找纯文件而不是目录,符号链接,设备...(.),并且我们希望将文件按o年龄升序排序(基于m修改时间,就像这样ls -t做)。

答案2

在类似的情况下,我使用了以下方法(可能这不是最强大的解决方案,但在常见情况下它仍然可能有用......)

LOGDIR=my/logs    ## 

ls -dpt -- "$LOGDIR"/log* | # get log files sorted by date
  grep -v '/$'            | # but remove directories/ from the list
  tail -n +4              | # remove also the newest 3
  vidir -

在 中vidir,如果您同意,请删除所有行(例如:使用dGvim 命令),然后离开,它们就会被删除。

vidirfrommoreutils是目录的投影编辑器(查看、重命名、删除目录内容的最佳工具)

答案3

这将为您提供除最新文件之外的所有文件的列表limit_files,然后您可以将其删除。

FileList=`ls -1rt ${ZK_PATH}/*log* | head -${limit_files}`
rm $FileList

它不适用于包含空格或其他特殊字符的文件,但我的日志目录中的日志文件仅包含字母数字字符、破折号和句点,因此可以完美运行。

相关内容