Bash 使用Unix查找计数并删除旧文件
我想删除Bash 使用Unix查找计数并删除旧文件,bash,unix,ksh,Bash,Unix,Ksh,我想删除$DIR\u to\u CLEAN中早于$DAYS\u to\u SAVEDAYS的文件。简单: find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE -exec rm {} \; 我想我们可以为rm添加-type f或-f标志,但我确实想计算删除的文件数 我们可以天真地这样做: DELETE_COUNT=`find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE | wc -l` find "$DIR_TO_CLEAN" -
$DIR\u to\u CLEAN
中早于$DAYS\u to\u SAVE
DAYS的文件。简单:
find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE -exec rm {} \;
我想我们可以为rm
添加-type f
或-f
标志,但我确实想计算删除的文件数
我们可以天真地这样做:
DELETE_COUNT=`find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE | wc -l`
find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE -exec rm {} \;
但这一解决方案仍有许多不足之处。除了命令重复之外,如果rm
删除文件失败,此代码段还会高估计数
我对重定向、管道(包括命名的管道)、子shell、xargs
、tee
等非常熟悉,但我渴望学习新技巧。我想要一个同时适用于bash和ksh的解决方案
如何计算被
find
删除的文件数?您可以在find中使用bash:
find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE -exec bash -c 'printf "Total: %d\n" $#; rm "$@"' _ {} +
当然,如果找到的文件数大于MAX_ARGS,则可以多次调用bash-c…
,如果rm失败,它还可能高估计数。但解决这些问题会变得一团糟:
find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE -exec bash -c 'printf "count=0; for f; do rm "$f" && (( count++ )); done; printf "Total: %d\n" $count' _ {} +
这种避免最大参数限制的解决方案完全避免了查找。如果您需要它是递归的,那么您必须使用递归全局绑定,这只在较新的shell中可用。(globstar
是bash4的一项功能。)
这里有一种将find与printf结合使用的方法(严格兼容的find没有printf,但在这种情况下,您可以将printf作为一个独立的实用程序使用)
我会避免使用
-exec
,而选择管道式解决方案:
find "$DIR_TO_CLEAN" -type f -mtime +$DAYS_TO_SAVE -print0 \
| awk -v RS='\0' -v ORS='\0' '{ print } END { print NR }' \
| xargs -0 rm
使用awk
对匹配项进行计数并将其传递给rm
更新:
kojiro让我意识到上述解决方案不包括rm
的成功/失败率。由于awk
存在名称不正确的文件问题,我认为以下bash
解决方案可能更好:
查找“${DIR\u TO_CLEAN?}”-键入f-mtime+${DAYS\u TO_SAVE?}-print0|
(
成功=0失败=0
读取-rd$'\0'文件时;执行以下操作
如果rm“$file”2>/dev/null;则
((success++)
其他的
((失败++))
fi
完成
echo$success$fail
)
否的可能重复,这不是重复。另一个问题并没有询问或解决当-exec
ed命令失败时计数会发生什么情况。我喜欢一个好的单行程序,但我将继续循环,可能是通过管道将find
导入其中。应该是继我之后的任何人最容易维护的,避免了最大参数问题,并允许轻松访问rm
返回代码。谢谢大家!@Prashant不使用管道查找,这很危险:如果您的文件名中有新行怎么办?在读取文件时查找“$DIR_TO_CLEAN”-mtime+$DAYS_TO_SAVE;执行rm“$FILE”;完成
引用“$FILE”只处理空格,不处理换行符?啊,我已经测试过了,现在明白你关于换行符的观点了,小二郎。谢谢你的洞察力。我后来为任何读者找到了一个。这个答案将计算rm
未能删除的文件。另外,作为一种边缘情况,xargs
受MAX_ARGS或其-n
选项的限制。@kojiro:是的,没有检查rm
是否成功xargs
自动调用rm
所需的次数,还是我误解了你的评论?这是一个微妙的问题,但这个问题与作为复制品提出的“计算文件数”问题的区别在于,这个问题问到如何只计算成功删除的文件数。啊,我明白了,我没有注意到这一点。我添加了一个bash解决方案,应该可以做到这一点。@Thor,我去掉了尾部,得到了一个“纯”shell解决方案。
find "$DIR_TO_CLEAN" -type -f -mtime "+$DAYS_TO_SAVE" -exec rm {} \; -printf '.' | wc -c
find "$DIR_TO_CLEAN" -type -f -mtime "+$DAYS_TO_SAVE" -exec rm {} \; -exec printf '.' \; | wc -c
find "$DIR_TO_CLEAN" -type f -mtime +$DAYS_TO_SAVE -print0 \
| awk -v RS='\0' -v ORS='\0' '{ print } END { print NR }' \
| xargs -0 rm