如果其他目录中存在超过 15 天的文件,请删除该文件

如果其他目录中存在超过 15 天的文件,请删除该文件

我有两个文件夹:“/media/downloads/”和“/home/uploads/” 我想删除“/media/downloads/”上 15 年前的文件(如果“/home/uploads/”中存在)

执行此操作的最佳脚本是什么?

先感谢您。

答案1

zsh

cd /home/uploads
uploaded_files=( **/*(ND.) )
cd /media/downloads
old_downloads=( **/*(ND.m+14) )
echo rm -- ${old_downloads:*uploaded_files}

(删除echo来实际删除文件)。

/media/downloads如果相同路径下的常规文件存在于/home/uploads.请注意,它不会检查它们是否具有相同的内容。

作为一个脚本,它可能看起来像:

#! /bin/zsh -
die() {
  print -ru2 -C1 -- "$@"
  exit 1
}

usage() {
  die "$@" "Usage: $ZSH_SCRIPT:t [-d <days>] [-n] <srcdir> <dstdir>"       \
  ''                                                                \
  '  Removes files from <srcdir> if their age rounded down to an'   \
  '  integer number of days is strictly greater than <days> (14 by' \
  '  default). -n for dry-run'
  exit 1
}

zmodload zsh/system || die

dryrun=0 days=14
while getopts nd: o; do
  case $o in
    (n) dryrun=1;;
    (d) days=$OPTARG;;
    (*) usage;;
  esac
done

shift OPTIND-1
(( $# == 2 )) || usage
[[ $days = <0-> ]] || usage "$days is not a positive decimal integer"

src=$1 dst=$2

[[ -d $src ]] || die "$src is not a directory"
[[ -d $dst ]] || die "$dst is not a directory"

list() {
  local dir=$1 var=$2 qual=$3 err
  ERRNO=0
  () { eval $var'=( "${@#$dir/}" )'; } $dir/**/*(ND.$qual)
  if (( ERRNO )); then
    syserror -e err
    die "An error was encountered during $dir traversal: $err"
  fi
}

list $src old_in_src m+$days
list $dst all_in_dst oN
to_remove=( ${old_in_src:*all_in_dst} )

if (( dryrun )); then
  if (( $#to_remove )); then
    print -ru2 -C1 "$#old_in_src old files found in $src, out of which $#to_remove are also found in $dst:" ' - '$^to_remove
  else
    print -ru2 "No file found to remove ($#old_in_src old files in $src in total)"
  fi
else
  rm -f -- $src/$^to_remove
fi

答案2

使用findbash

find /media/downloads/ -type f -mtime +15 \
  -exec bash -c 'for f; do
                   f2=${f/"/media/downloads/"/}
                   test -e "/home/uploads/$f2" && delfiles+=("$f");
                 done;
                 [ -n "$delfiles" ] && printf "rm %q\n" -- "${delfiles[@]}"' bash {} +

find查找所有超过 15 天的常规文件,并将它们作为参数传递给bash.对于每个文件名,bash 会从文件名中删除顶级目录 ( /media/downloads/),然后检查文件名的其余部分(包括子目录,如果有的话)是否存在于/home/uploads/.如果是,则会将该文件添加到名为 的数组中$delfiles

一旦迭代完所有文件名参数,它就会打印数组中的每个文件名。

这是作为试运行编写的,因此只会展示如果不实际做的话它会做什么。要使其真正删除文件,请更改printf "rm %q\n" --rm --

它永远不会删除任何目录,即使它们的内容被删除后是空的。如果您需要这样做,您可以在删除文件后运行如下命令(使用 GNU find)。

find /media/downloads/ -mindepth 1 -type d -empty -delete

另外值得注意的是: 和 都zsh具有类似的参数扩展和字符串修改功能,因此使用or代替 bashksh应该很简单(可能只需要更改为or但我还没有测试过,所以不能肯定地说- bash 和那些 shell 之间可能存在细微差别)。zshkshbash -cksh -czsh -c


¹查看man find并搜索-atime有关如何计算的详细信息 - 您可能会发现它-mtime 14更适合您。如果感兴趣的话,查找的-daystart选项也可能是。

相关内容