So we want to get the (regular) files that have mtime
more than 7 days ago AND are not within the 20 newest files.
One way to do that is to construct a list of files along with their modification times and a flag indicating whether the file is mtime +7
or not. We can then sort the list by mtime
, and take all but the 20 most recent1. Finally, iterate over the resulting list and delete only those that meet the age threshold:
find ./recentpicturesdirectory -type f \( -mtime +7 -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
sort -zk2,2 | head -zn -20 | while read -r -d '' flag _ file; do \
case "$flag" in
'Y') echo rm "$file"
;;
*) echo "skipping $file (too new)"
;;
esac
done
By using \0
termination and adding the -z
flag to the sort
and head
(or tail
) commands, we can handle any legal filenames without choking on whitespace.
The echo
is added for testing purposes; remove it once you're certain that the desired files are selected for deletion.
1 If we sort in ascending order of mtime (i.e. old to new), we can use head -n -20
to select all but the last 20; alternatively we could sort in descending order of mtime (new to old) and use tail -n +21
If you have zsh
, then you can do it all with glob qualifiers, I think:
rm ./recentpicturesdirectory/**/*(.^om[1,20]^m+7)
where
**/*
matches recursively (equivalent of bash globstar
)
(.)
match regular files only
om[1,20]
lists results in ascending order of mtime, and select the first 20
m+7
match only files with mtime
> 7 days
^
invert everything that follows
so the logic is
regular files NOT (in 20 most recent by mtime OR NOT mtime +7 days)
which (by application of de Morgan's rules) is equivalent to
regular files (NOT in 20 most recent by mtime) AND (mtime +7 days)
Please do a trial run first though e.g.
print -rl ./recentpicturesdirectory/**/*(.^om[1,20]^m+7)