我想删除某个目录中的所有日志文件,但不是最新的 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
,并且括号(…)
指定如果没有找到文件,则没有错误(N
ullglob),我们只查找纯文件而不是目录,符号链接,设备...(.
),并且我们希望将文件按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
,如果您同意,请删除所有行(例如:使用dG
vim 命令),然后离开,它们就会被删除。
vidir
frommoreutils
是目录的投影编辑器(查看、重命名、删除目录内容的最佳工具)
答案3
这将为您提供除最新文件之外的所有文件的列表limit_files
,然后您可以将其删除。
FileList=`ls -1rt ${ZK_PATH}/*log* | head -${limit_files}`
rm $FileList
它不适用于包含空格或其他特殊字符的文件,但我的日志目录中的日志文件仅包含字母数字字符、破折号和句点,因此可以完美运行。