我正在尝试保持一个充满日志文件的目录可管理。每晚,我想删除除最近的10个以外的所有内容。我怎样才能在一个命令中执行此操作?
我正在尝试保持一个充满日志文件的目录可管理。每晚,我想删除除最近的10个以外的所有内容。我怎样才能在一个命令中执行此操作?
Answers:
对于便携可靠的解决方案,请尝试以下方法:
ls -1tr | head -n -10 | xargs -d '\n' rm -f --
其中tail -n -10
一个答案中的语法似乎无处不在(即,不在我的RHEL5系统上)。
使用$()
或``
在命令行上rm
运行的风险
xargs
修复了这两个问题,因为它会自动计算出它在字符数限制内可以传递多少个args,并且-d '\n'
它只会在输入的行边界处分割。从技术上讲,这仍然会导致文件名中出现换行问题,但这远远不如带有空格的文件名常见,并且围绕换行的唯一方法就是复杂得多,可能至少涉及awk,如果不是perl。
如果您没有xargs(可能是旧的AIX系统?),您可以将其设为循环:
ls -1tr | head -n -10 | while IFS= read -r f; do
rm -f "$f"
done
这会有点慢,因为它会rm
为每个文件生成一个单独的文件,但仍然会避免上面的警告1和2(但仍然会受到文件名中的换行符的影响)。
head(1)
手册页:-n, --lines=[-]K print the first K lines instead of the first 10; with the leading '-', print all but the last K lines of each file
head
并xargs
给出错误。正确的选择是head -n 10
和xargs rm -f
。完全命令是ls -1tr ./ | head -n 10 | xargs rm -rf
ls -1tr
是数字ONE而不是字母“L”。
您希望包含在脚本中的代码是
rm -f $(ls -1t /path/to/your/logs/ | tail -n +11)
该-1
(数字1)选项打印在一行上的每个文件,是安全的。告诉它忽略不存在的文件什么时候什么都不返回的-f
选项。rm
ls
/path/to/your/logs
只是为了让你进入正确的道路。要找到错误执行部件ls -t /path/...
并ls -t /path/... | tail -n +11
单独检查结果是否正确。
+
之前的数字。它tail
不会打印最后n个元素,而是从n个开始的所有元素。我再次签入,命令肯定应该删除所有情况下只有10个最新文件的元素。
ls
打印文件名,而不是路径所以你rm -f
会尝试删除当前目录中的文件
显然解析ls
是邪恶的。
如果每天都创建每个文件,并且您希望保留在过去10天内创建的文件,则可以执行以下操作:
find /path/to/files -mtime 10 -delete
或者,如果每个文件是任意创建的:
find /path/to/files -maxdepth 1 -type f -printf '%Ts\t%P\n' | sort -n | head -n -10 | cut -f 2- | xargs rm -rf
-mtime 10 -delete
仅删除10天前修改过的文件。旧文件不会被删除。-mtime +11 -delete
将删除11天或更久前修改过的文件,留下最后10天的日志文件。
%p
,而不是%P
需要的printf
,这样的文件得到了具有完整路径。否则rm -rf
不起作用。
从这里:
#! /bin/sh
# keepnewest
#
# Simple directory trimming tool to handle housekeeping
# Scans a directory and deletes all but the N newest files
#
# Usage: cleanup <dir> <number of files to keep>
#
# v 1.0 Piers Goodhew 1/mar/2007. No rights retained.
if [ $# -ne 2 ]; then
echo 1>&2 "Usage: $0 <dir> <number of files to keep>"
exit 1
fi
cd $1
files_in_dir=`ls | wc -l`
files_to_delete=`expr $files_in_dir - $2`
if [ $files_to_delete -gt 0 ]; then
ls -t | tail -n $files_to_delete | xargs rm
if [ $? -ne 0 ]; then
echo "An error ocurred deleting the files"
exit 1
else
echo "$files_to_delete file(s) deleted."
fi
else
echo "nothing to delete!"
fi
在Bash中你可以尝试:
ls -1t | (i=0; while read f; do
if [ $i -lt 10 ]; then
((i++))
continue
else
rm -f "$f"
fi
done)
这跳过10个最新的als删除其余的。logrotate可能更好,我只是想纠正错误的shell相关答案。
我需要一个优雅的busybox(路由器)解决方案,所有的xargs或阵列解决方案对我来说都没用 - 没有这样的命令。find和mtime不是正确的答案,因为我们正在谈论10个项目,而不一定是10天。Espo的答案是最短,最干净,也可能是最不可逆的答案。
空格出错以及没有要删除的文件都是以标准方式解决的:
rm "$(ls -td *.tar | awk 'NR>7')" 2>&-
更多教育版:如果我们使用awk的话,我们可以做到这一切。通常,我使用此方法将变量从awk传递(返回)到sh。当我们阅读所有无法完成的时间时,我不同意:这是方法。
.tar文件的示例,文件名中的空格没有问题。要测试,请将“rm”替换为“ls”。
eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}')
说明:
ls -td *.tar
列出按时间排序的所有.tar文件。要应用于当前文件夹中的所有文件,请删除“d * .tar”部分
awk 'NR>7...
跳过前7行
print "rm \"" $0 "\""
构造一行:rm“文件名”
eval
执行它
由于我们正在使用rm
,我不会在脚本中使用上面的命令!更明智的用法是:
(cd /FolderToDeleteWithin && eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}'))
在使用ls -t
命令的情况下,不会对如下愚蠢的例子造成任何伤害:touch 'foo " bar'
和touch 'hello * world'
。并非我们在现实生活中创建具有此类名称的文件!
边注。如果我们想以这种方式将变量传递给sh,我们只需修改print:
print "VarName="$1
将变量VarName
设置为值$1
。可以一次创建多个变量。这VarName
成为一个普通的sh变量,之后通常可以在脚本或shell中使用。因此,使用awk创建变量并将它们返回给shell:
eval $(ls -td *.tar | awk 'NR>7 { print "VarName="$1 }'); echo "$VarName"