Jis*_*air 4 bash shell-script rm files
我正在尝试创建一个脚本并每 5 分钟在 crontab 中运行它,以便文件夹中的文件数始终保持 50000。如果还有更多,我希望脚本删除旧文件。
#!/bin/bash
LIMIT=500000
NO=0
#Get the number of files, that has `*.pcap` in its name, with last modified time 5 days ago
NUMBER=$(find /mnt/md0/capture/DCN/ -maxdepth 1 -name "*.pcap" |wc -l)
if [[ $NUMBER -gt $LIMIT ]] #if number greater than limit
then
del=$(($NUMBER-$LIMIT))
if [ "$del" -lt "$NO" ]
then
del=$(($del*-1))
fi
echo $del
FILES=$(
find /mnt/md0/capture/DCN/ -maxdepth 1 -type f -name "*.pcap" -print0 |
xargs -0 ls -lt |
tail -$del |
awk '{print $8}'
)
rm -f ${FILES[@]}
#delete the originals
fi
Run Code Online (Sandbox Code Playgroud)
它实际上不起作用,因为文件数量太大而无法运行。有没有其他方法可以完成这项工作?
对于那些不想对文件名做出假设的人:
与zsh
:
#! /bin/zsh -
keep=5000
rm -f /mnt/md0/capture/DCN/*.pcap(D.om[$((keep+1)),-1])
Run Code Online (Sandbox Code Playgroud)
那是使用zsh
通配符限定符:
D
:包括隐藏文件(d加时赛文件)。.
: 仅常规文件(如find
's -type f
)om
:反向Ó(基于关于年龄刻申米odification时间)[$((keep+1)),-1]
:只包括5001 ST到最后。(如果要删除的文件列表是非常大的,可能会失败,在这种情况下,你可能想使用zargs
拆分它,或启用zsh
的内置rm
带zmodload zsh/files
)。
使用相对较新版本的 GNU 工具:
cd /mnt/md0/capture/DCN/ &&
find . -maxdepth 1 -name '*.pcap' -type f -printf '%T@@%p\0' |
sort -zrn | sed -z "s/[^@]*@//;1,$keep d" | xargs -r0 rm -f
Run Code Online (Sandbox Code Playgroud)
(假设 GNU sed 4.2.2 或更高版本(2012)用于-z
,GNU sort
1.14 或更高版本(1996)用于-z
)
find
构建一个 NUL 分隔的文件名列表,并带有 Unix 时间戳(如1390682991.0859627500@./file
),按 排序sort
。sed
删除时间戳只有从5001打印ST纪录。这作为参数传递给rm
using xargs -r0
。
或(使用任何版本的 GNU 工具):
cd /mnt/md0/capture/DCN/ &&
find . -maxdepth 1 -name '*.pcap' -type f -printf '%T@@%p\0' |
tr '\0\n' '\n\0' | sort -rn | tail -n "+$(($keep+1))" |
cut -d @ -f2- | tr '\0\n' '\n\0' | xargs -r0 rm -f
Run Code Online (Sandbox Code Playgroud)
相同,除了我们使用cut
删除时间戳并tail
选择从 5001 开始的行。因为 GNUcut
和tail
不支持-z
处理 NUL 分隔的记录,我们使用tr
在输入之前和之后交换换行符和 NUL 字符数据给他们。
使用 GNU ls
(4.0(1998)或更高版本),以及bash
:
shopt -s dotglob
cd /mnt/md0/capture/DCN/ &&
eval "files=($(ls -dt --quoting-style=shell-always -- *.pcap))" &&
rm -f -- "${files[@]:$keep}"
Run Code Online (Sandbox Code Playgroud)
(如果文件列表很大,这也可能会失败。另请注意,它可能包含非常规的 pcap 文件(否-type f
))。
标准/POSIXly/便携,这要棘手得多:
cd /mnt/md0/capture/DCN/ &&
ls -dt ./.pcap ./.*.pcap ./*.pcap | awk -v keep="$keep" '
function process() {
if (++n > keep) {
gsub(/[ \t\n"\\'\'']/,"\\\\&", file)
print file
file = ""
}
}
/\// {
if (NR > 1) process()
file=$0
next
}
{file = file "\n" $0}
END {if (NR > 0) process()}' | xargs rm -f
Run Code Online (Sandbox Code Playgroud)
(同样,您可能会达到参数数量的限制,并且它不会检查常规文件)。
棘手的一点是用换行符处理文件名。以上,我们传递./*
给ls
该装置/
将包括一次为每个文件名,我们使用,在awk
识别上线每个文件名开始,我们就知道这换行符(除了所有其他的人特xargs
)到逃跑xargs
。