Linux Shell 脚本来计算文件,然后删除最旧的文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2960022/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Shell script to count files, then remove oldest files
提问by Nic Hubbard
I am new to shell scripting, so I need some help here. I have a directory that fills up with backups. If I have more than 10 backup files, I would like to remove the oldest files, so that the 10 newest backup files are the only ones that are left.
我是 shell 脚本的新手,所以我需要一些帮助。我有一个充满备份的目录。如果我有 10 个以上的备份文件,我想删除最旧的文件,以便只剩下 10 个最新的备份文件。
So far, I know how to count the files, which seems easy enough, but how do I then remove the oldest files, if the count is over 10?
到目前为止,我知道如何计算文件数,这似乎很容易,但是如果计数超过 10,我该如何删除最旧的文件?
if [ls /backups | wc -l > 10]
then
echo "More than 10"
fi
采纳答案by Dale Hagglund
Try this:
尝试这个:
ls -t | sed -e '1,10d' | xargs -d '\n' rm
This should handle all characters (except newlines) in a file name.
这应该处理文件名中的所有字符(换行符除外)。
What's going on here?
这里发生了什么?
ls -t
lists all files in the current directory in decreasing order of modification time. Ie, the most recently modified files are first, one file name per line.sed -e '1,10d'
deletes the first 10 lines, ie, the 10 newest files. I use this instead oftail
because I can never remember whether I needtail -n +10
ortail -n +11
.xargs -d '\n' rm
collects each input line (without the terminating newline) and passes each line as an argument torm
.
ls -t
按修改时间降序列出当前目录中的所有文件。即,最近修改的文件是第一个,每行一个文件名。sed -e '1,10d'
删除前 10 行,即 10 个最新的文件。我使用它而不是tail
因为我永远不记得我是否需要tail -n +10
或tail -n +11
.xargs -d '\n' rm
收集每个输入行(没有终止换行符)并将每一行作为参数传递给rm
.
As with anything of this sort, please experiment in a safe place.
与此类任何事情一样,请在安全的地方进行试验。
回答by barrycarter
Experiment with this, because I'm not 100% sure it'll work:
对此进行试验,因为我不是 100% 确定它会起作用:
cd /backups; ls -at | tail -n +10 | xargs -I{} "rm '{}'"
回答by bta
stat -c "%Y %n" * | sort -rn | head -n +10 | \
cut -d ' ' -f 1 --complement | xargs -d '\n' rm
Breakdown: Get last-modified times for each file (in the format "time
filename
"), sort them from oldest to newest, keep all but the last ten entries, and then keep all but the first field (keep only the filename portion).
细分:获取每个文件的最后修改时间(格式为“ time
filename
”),将它们从最旧到最新排序,保留除最后十个条目之外的所有条目,然后保留除第一个字段之外的所有条目(仅保留文件名部分)。
Edit: Using cut
instead of awk
since the latter is not always available
编辑:使用cut
而不是awk
因为后者并不总是可用
Edit 2: Now handles filenames with spaces
编辑 2:现在处理带空格的文件名
回答by Paused until further notice.
回答by bashfu
Using inode numbers via stat & find command (to avoid pesky-chars-in-file-name issues):
通过 stat & find 命令使用 inode 编号(以避免麻烦的文件名字符问题):
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
回答by Daniel Haley
I like the answers from @Dennis Williamson and @Dale Hagglund. (+1 to each)
我喜欢@Dennis Williamson 和@Dale Haglund 的回答。(每个+1)
Here's another way to do it using find
(with the -newer
test) that is similar to what you started with.
这是使用find
(通过-newer
测试)的另一种方法,类似于您开始使用的方法。
This was done in bash on cygwin...
这是在 cygwin 上的 bash 中完成的...
if [[ $(ls /backups | wc -l) > 10 ]]
then
find /backups ! -newer $(ls -t | sed '11!d') -exec rm {} \;
fi
回答by mikecolley
Make sure your pwd is the correct directory to delete the files then(assuming only regular characters in the filename):
确保您的密码是删除文件的正确目录(假设文件名中只有常规字符):
ls -A1t | tail -n +11 | xargs rm
keeps the newest 10 files. I use this with camera program 'motion' to keep the most recent frame grab files. Thanks to all proceeding answers because you showed me how to do it.
保留最新的 10 个文件。我将它与相机程序“运动”一起使用以保留最新的帧抓取文件。感谢所有进行中的答案,因为您向我展示了如何去做。
回答by John Andrea
Straightforward file counter:
简单的文件计数器:
max=12
n=0
ls -1t *.dat |
while read file; do
n=$((n+1))
if [[ $n -gt $max ]]; then
rm -f "$file"
fi
done
回答by mahyard
find
is the common tool for this kind of task :
find
是这种任务的常用工具:
find ./my_dir -mtime +10 -type f -delete
EXPLANATIONS
说明
./my_dir
your directory (replace with your own)-mtime +10
older than 10 days-type f
only files-delete
no surprise. Remove it to test yourfind
filter before executing the whole command
./my_dir
您的目录(替换为您自己的)-mtime +10
超过 10 天-type f
只有文件-delete
没有惊喜。在执行整个命令之前删除它以测试您的find
过滤器
And take care that ./my_dir
exists to avoid bad surprises !
并注意./my_dir
存在以避免糟糕的惊喜!
回答by miron
On a very limited chroot environment, we had only a couple of programs available to achieve what was initially asked. We solved it that way:
在非常有限的 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
Explanation:
解释:
FILE_COUNT=$(ls -l | grep -c ^d )
counts all files in the current folder. Instead of grep we could use alsowc -l
but wc was not installed on that host.FILE_COUNT=$[$FILE_COUNT-1]
update the current$FILE_COUNT
FILE_TO_DEL=$(ls -t | tail -n1)
Save the oldest file name in the$FILE_TO_DEL
variable.tail -n1
returns the last element in the list.
FILE_COUNT=$(ls -l | grep -c ^d )
计算当前文件夹中的所有文件。我们也可以使用 grep 代替 grep,wc -l
但该主机上未安装 wc。FILE_COUNT=$[$FILE_COUNT-1]
更新当前$FILE_COUNT
FILE_TO_DEL=$(ls -t | tail -n1)
将最旧的文件名保存在$FILE_TO_DEL
变量中。tail -n1
返回列表中的最后一个元素。