3

I have written this script:

#!/bin/bash
DAYSOLD="2"
users_dir="/users"
cd $users_dir
date >> cleanup.log;  du -h --max-depth=1 | sort -hr >> cleanup.log
find $users_dir -mtime +$DAYSOLD -type f -exec rm -v {} \;

I would like to delete files only under the "workspace" directory and older than 2 days. How should this be done?

/users/user1/workspace
/users/user2/workspace
/users/user3/workspace

Thanks for helping. I would love to learn how to do this.

Tom S
  • 145

2 Answers2

6

-mtime "+$days" selects files whose age (based on last modification time) rounded down to an integer number of days is stricktly greater than $days.

A file that is 2 days and 23 hours old would not be selected by -mtime +2 because, it's considered to be 2 day old which is not greater than 2.

So you need:

find "$users_dir"/*/workspace -mtime "+$(( DAYSOLD - 1 ))" -type f -delete

To delete files that are older than $DAYSOLD days¹ in any workspace directory² found in any subdirectory³ of $users_dir. Though you could also do:

find "$users_dir"/*/workspace '(' -mtime "$DAYSOLD" -o -mtime "+$DAYSOLD" ')' \
                   -type f -delete

Which deletes files whose age (in integer number of days) is either $DAYSOLD or greater than $DAYSOLD.

-delete is a non-standard extension, but is available in GNU find as found on Ubuntu and is safer and more efficient than using -exec rm. You can make it -delete -print if you want the list of files that have been successfully deleted.

Also remember to quote your variables and check the exit status of cd before carrying one: (cd -P -- "$users_dir" && exec du...) or du would run in the wrong directory if cd failed. Also note the use of a subshell or it wouldn't work properly if $users_dir was a relative path. It would actually make more sense to write it as:

cd -P -- "$users_dir" || exit
du ...
find . ...

(which would be more consistent if $users_dir was a symlink)


¹ strictly speaking, that's at least $DAYSOLD days old but considering that the comparison is done using nanosecond precision and that it takes several hundred nanoseconds to start find, that distinction is hardly relevant.

² strictly speaking, if workspace is a file that is not of type directory, that will still be passed to find, and if that file is older than $DAYSOLD days (and is a regular files for -type f), it will be deleted as well. You could switch to zsh and add (/) to the pattern to make sure only workspace files of type directory are considered. Do not just append / as you'd run into ³ below with more severe consequences (like when /users/joe/workspace is a symlink to /bin or /).

³ Note that symlinks are followed there. So if /users/joe is a symlink to / for instance, that will delete old files in the /workspace directory.

2

try with this

find $users_dir/user*/workspace -mtime +$DAYSOLD -type f -exec echo rm -v {} \;

if it does what you're expecting drop the echo. Consider adding -daystart if you want to consider the days as from midnight

Another easy way is using -path

find  $users_dir -path "$users_dir/user*/workspace/*" -mtime +$DAYSOLD -type f -exec echo rm -v {} \;
  • 1
    -path "$users_dir/user*/workspace/*" would also delete old files in /users/user1/other/dir/workspace (and the whole of $users_dir would be scanned). – Stéphane Chazelas Nov 15 '21 at 11:21
  • your'e right.. it treats / as a matching pattern.. try with this find . ( -path "./user[^/]/workspace/" -or -path "./user[^/][^/]/workspace/" ) -type f -mtime $DAYSOLD -type f -exec echo rm -v {} ; – fusillator Nov 16 '21 at 13:44