我是shell脚本的新手,所以我需要一些帮助。我有一个填满备份的目录。如果我有10个以上的备份文件,我想删除最旧的文件,这样就可以删除10个最新的备份文件。
到目前为止,我知道如何计算文件,这看起来很容易,但如果计数超过10,我如何删除最旧的文件?
if [ls /backups | wc -l > 10]
then
echo "More than 10"
fi
答案 0 :(得分:85)
试试这个:
ls -t | sed -e '1,10d' | xargs -d '\n' rm
这应该处理文件名中的所有字符(换行符除外)。
这里发生了什么?
ls -t
按修改时间的降序列出当前目录中的所有文件。即,最近修改的文件是第一个,每行一个文件名。sed -e '1,10d'
删除前10行,即10个最新文件。我使用此代替tail
,因为我永远不会记得我是否需要tail -n +10
或tail -n +11
。xargs -d '\n' rm
收集每个输入行(没有终止换行符)并将每行作为参数传递给rm
。与此类任何事情一样,请在安全的地方进行实验。
答案 1 :(得分:23)
find
是执行此类任务的常用工具:
find ./my_dir -mtime +10 -type f -delete
<强>说明强>
./my_dir
您的目录(替换为您自己的目录)-mtime +10
超过10天-type f
仅限文件-delete
毫不奇怪。 删除它以在执行整个命令之前测试find
过滤器 并注意./my_dir
存在以避免不良意外!
答案 2 :(得分:12)
执行此类事情的正确方法是使用logrotate
。
答案 3 :(得分:6)
确保你的pwd是删除文件的正确目录(假设文件名中只有常规字符):
ls -A1t | tail -n +11 | xargs rm
保留最新的10个文件。我用相机程序'motion'来保存最新的帧抓取文件。感谢所有正在进行的答案,因为你告诉我该怎么做。
答案 4 :(得分:3)
我喜欢@Dennis Williamson和@Dale Hagglund的答案。 (每个+1)
以下是使用find
(使用-newer
测试)与您开始时类似的另一种方法。
这是在cygwin的bash中完成的......
if [[ $(ls /backups | wc -l) > 10 ]]
then
find /backups ! -newer $(ls -t | sed '11!d') -exec rm {} \;
fi
答案 5 :(得分:2)
直截了当的档案柜台:
max=12
n=0
ls -1t *.dat |
while read file; do
n=$((n+1))
if [[ $n -gt $max ]]; then
rm -f "$file"
fi
done
答案 6 :(得分:1)
stat -c "%Y %n" * | sort -rn | head -n +10 | \
cut -d ' ' -f 1 --complement | xargs -d '\n' rm
细分:获取每个文件的最后修改时间(格式为“time
filename
”),从最旧到最新排序,保留除最后十个条目以外的所有文件,然后保留所有文件但是第一个字段(仅保留文件名部分)。
修改:使用cut
代替awk
,因为后者并非始终可用
编辑2 :现在处理带空格的文件名
答案 7 :(得分:1)
在非常有限的chroot环境中,我们只有几个程序可用于实现最初的问题。我们这样解决了:
MIN_FILES=5
FILE_COUNT=$(ls -l | grep -c ^d )
if [ $MIN_FILES -lt $FILE_COUNT ]; then
while [ $MIN_FILES -lt $FILE_COUNT ]; do
FILE_COUNT=$[$FILE_COUNT-1]
FILE_TO_DEL=$(ls -t | tail -n1)
# be careful with this one
rm -rf "$FILE_TO_DEL"
done
fi
<强>解释强>
FILE_COUNT=$(ls -l | grep -c ^d )
计算当前文件夹中的所有文件。我们也可以使用wc -l
而不是grep,但是没有在该主机上安装wc。FILE_COUNT=$[$FILE_COUNT-1]
更新当前的$FILE_COUNT
FILE_TO_DEL=$(ls -t | tail -n1)
将最旧的文件名保存在$FILE_TO_DEL
变量中。 tail -n1
返回列表中的最后一个元素。答案 8 :(得分:1)
我刚刚找到了这个主题,mikecolley的解决方案在第一步中对我有所帮助。由于我需要单行Homematic(Raspberrymatic)脚本的解决方案,因此遇到一个问题,该命令仅给我文件名,而不是“ rm
”所需的整个路径。我使用的CUxD Exec命令无法在所选文件夹中启动。
这是我的解决方法:
ls -A1t $(find /media/usb0/backup/ -type f -name homematic-raspi*.sbk) | tail -n +11 | xargs rm
解释:
find /media/usb0/backup/ -type f -name homematic-raspi*.sbk
仅搜索命名为-type f
(区分大小写)或使用-name homematic-raspi*.sbk
(不区分大小写)的文件夹-iname
ls -A1t $(...)
列出find
给出的文件,但不包括以“。”开头的文件。或“ ..” -A
按mtime -t
排序,仅返回一列-1
tail -n +11
仅返回最后{strong> 10 -n +11
行,以跟随rm
xargs rm
,最后删除列表中的Raiming文件也许这可以帮助其他人进行更长的搜索,并使解决方案更加灵活。
答案 9 :(得分:0)
基于其他建议和一些awk foo,我可以使用它。我知道这是一个老话题,但是我在这里找不到合适的答案,因此为我进行了排序。这只会删除最旧的文件,但是您可以将head -n 1更改为10,并获取最旧的文件10。
找到$ DIR -type f -printf'%T +%p \ n'|排序头-n 1 | awk'{first = $ 1; $ 1 =“”;打印$ 0}'| xargs -d'\ n'rm
答案 10 :(得分:-2)
通过stat&amp; amp;使用inode号码find命令(以避免讨厌文本名称问题):
stat -f "%m %i" * | sort -rn -k 1,1 | tail -n +11 | cut -d " " -f 2 | \
xargs -n 1 -I '{}' find "$(pwd)" -type f -inum '{}' -print
#stat -f "%m %i" * | sort -rn -k 1,1 | tail -n +11 | cut -d " " -f 2 | \
# xargs -n 1 -I '{}' find "$(pwd)" -type f -inum '{}' -delete
答案 11 :(得分:-6)
试验一下,因为我不是100%确定它会起作用:
cd /backups; ls -at | tail -n +10 | xargs -I{} "rm '{}'"