您可以使用find 和-newerXY 选项(您否定)来执行此操作,其中XY 等于mt 用于修改时间,at 用于访问时间,ct 用于创建时间。您只需传递 -delete 即可删除匹配的文件名。你可以这样做:
d=$(date -d "30 days ago" '+%F %T') # get date and time 30 days ago
find ~/Downloads -type f ! -newermt "$d" ! -newerat "$d" ! -newerct "$d" -delete
(选项的顺序很重要,因为它们被评估为一个表达式,如果你把-delete放在第一位,它将删除~/Download路径下的所有文件,因为在@987654331之前没有任何东西可以修改文件列表遇到@)
注意:在不使用 -delete 的情况下进行测试,以确保它返回您期望的列表,然后重新添加选项以实际删除文件。
关于将问题更改为是否有任何文件在 Mod、Access 或 Change 中较新 -- 将所有内容保存在该目录中的想法
编辑后,子目录中的任何文件都将阻止删除子目录中的任何文件,这将阻止对 find 的单个调用有帮助,因为 find 在不知情的情况下一次处理单个文件对其他文件的测试是如何进行的。
在这里,我的想法是更多地循环遍历~/Downloads 下的目录,依赖于设置的globstar。您将更改到您的 "$HOME" 目录(在脚本中),因此 **/ 搜索生成的路径将与 "$HOME" 相关,而不会在它们前面附加其他无关的 /home/user 路径组件。
创建一个短函数,循环遍历正在处理的目录中的每个文件,如果任何一个文件在修改、访问或更改时更新,则对该目录不做任何操作,所有文件都将保存。
使用stat 快速实现使用日期和模式,访问和更改时间(以秒为单位),您可以这样做:
#!/bin/bash
shopt -s globstar # endable globstar globbing
dt=$(date -d "30 days ago" '+%s') # 30 days ago in seconds since epoch
cd "$HOME" || exit 1 # change to home directory path globbing to Downloads
dld="Downloads" # set Downloads varabile
# function returns 0 if no files in dir with access or mod time in 30 days
# returns 1 otherwise (don't remove)
nonenewerthan30 () {
local dir="$1"
[ -d "$dir" ] || return 1 # validate it is a dir
for f in "$dir"/*; do # loop over files in dir
[ -d "$f" ] && continue # skip any directories in dir
[ $(stat -c %X "$f") -gt "$dt" ] && return 1 # mod time since epoch
[ $(stat -c %Y "$f") -gt "$dt" ] && return 1 # access time since epoch
[ $(stat -c %Z "$f") -gt "$dt" ] && return 1 # change time since epoch
done
return 0 # directory can be removed.
}
for d in "$dld"/**/; do # loop Downloads and all subdirs
d="${d%/}" # remove trailing '/'
[ "$d" = "$dld" ] && continue # skip Downloads until subs processed
printf "\nprocessing: %s\n" "$d"
nonenewerthan30 "$d" && { # call func, on 0 return, remove sub
echo " can remove $d"
# rm -r "$d" # uncomment after your verify behavior
}
done
目前它会跳过处理Downloads 中的文件,直到所有子目录完成。您需要跟踪文件是否保留在任何级别,以了解是否将它们从Downloads 中删除甚至是一种选择。添加我留给你的逻辑。