使用Unix查找计算并删除旧文件

时间:2012-07-24 17:25:46

标签: bash unix ksh

我想删除早于$DIR_TO_CLEAN$DAYS_TO_SAVE的文件。易:

find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE -exec rm {} \;

我想我们可以为-type f添加-frm标记,但我真的想计算要删除的文件数。

我们可以天真地做到这一点:

DELETE_COUNT=`find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE | wc -l`
find "$DIR_TO_CLEAN" -mtime +$DAYS_TO_SAVE -exec rm {} \;

但是这个解决方案还有很多不足之处。除了命令重复之外,如果rm无法删除文件,此代码段会高估计数。

我对重定向,管道(包括命名的),子壳,xargstee等感到非常满意,但我渴望学习新的技巧。我想要一个适用于bash和ksh的解决方案。

您如何计算find删除的文件数量?

2 个答案:

答案 0 :(得分:5)

我会避免-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解决方案可能更好:

find "${DIR_TO_CLEAN?}" -type f -mtime +${DAYS_TO_SAVE?} -print0 |
(
  success=0 fail=0
  while read -rd $'\0' file; do 
  if rm "$file" 2> /dev/null; then 
    (( success++ ))
  else
    (( fail++ ))
  fi
  done
  echo $success $fail
)

答案 1 :(得分:1)

你可以在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' _ {} +

这种避免MAX_ARGS限制的解决方案完全避免了查找。如果你需要它是递归的,你将不得不使用递归globbing,它只在较新的shell中可用。 (globstar是一个bash 4功能。)

shopt -s globstar
# Assume DAYS_TO_SAVE reformatted to how touch -m expects it. (Exercise for the reader.)
touch -m "$DAYS_TO_SAVE" referencefile
count=0
for file in "$DIR_TO_CLEAN/"**/*; do
    if [[ referencefile -nt "$file" ]]; then
        rm "$file" && (( count++ ))
    fi
done
printf 'Total: %d\n' "$count"

这是一种使用find with printf的方法(严格兼容的find没有printf,但在这种情况下你可以使用printf作为独立的实用程序。)

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