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)"
\0 termination and adding the
-z flag to the
tail) commands, we can handle any legal filenames without choking on whitespace.
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:
**/* matches recursively (equivalent of bash
(.) 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)