2

I have a directory that gets a lot of data dumped into it, and I want to find all directories whose contents haven't been modified recently (e.g., in the last 5 days). I'm trying to compose a call to find that does what I'm looking for, but I'm starting to wonder if this is more complex than what find can handle. Here's what I've tried, which isn't doing quite what I expect:

find "$DUMP_DIR" -type d -d 2 \
    -execdir bash -c 'find . -mtime -5 >/dev/null 2>&1' \; \
    -prune

The directory structure is laid out like $DUMP_DIR/category{1,2,3,4,5}/thing* more or less. I want to know what thing* directories have had new data dumped somewhere inside of them recently. The naive solution find "$DUMP_DIR" -type d -d 2 -mtime +5 will match more than I want.

I expected that the -execdir expression will find out whether any directory contains something modified in the last five days (returning nonzero if nothing is found), but I guess it doesn't quite do that.

I'm stuck with the BSD find installed on OS X. I'd also rather not install anything not already a part of the standard command line utilities. What's the most reasonable way to do this?

  • I feel you... BSD find is truly hideous. :( – Nemo Oct 28 '15 at 11:06
1

I believe that this will do what you need. It looks through each directory in turn and checks that there are no "recently modified" files.

find * -type d |
    while read DIR
    do
        LINES=$(find "$DIR" -maxdepth 1 -type f -mtime -5 -print -quit)
        test -z "$LINES" && echo "$DIR NOT RECENTLY MODIFIED"
    done

If the find ... -maxdepth 1 doesn't work for your situation, feel free to change it to something like this

LINES=$(find "$DIR" \( -type d -prune \) -o \( -type f -mtime -5 -print -quit \))

And if you want to count the number of items recently modified (or if -quit isn't available), this will work

LINES=$(find "$DIR" -maxdepth 1 -type f -mtime -5 | wc -l | tr -d' ')
test 0 -eq "$LINES" && echo "$DIR NOT RECENTLY MODIFIED" || echo "$DIR has $LINES recent file(s)"
  • This looks reasonably good assuming that the file names aren't pathological. I don't suppose there's any way for the $(find ... | wc -l) to terminate immediately upon encountering the first file matching the criteria, is there? After all, I don't really need to count the number of recently modified files, I just want to know if there's at least one. – user108471 Feb 24 '15 at 18:48
  • It will handle filenames containing pretty much anything except \n. If your version of find supports it, you can try adding -false after the -print to exit as soon as a match is made. – roaima Feb 24 '15 at 20:23
  • At least on the version of find in OS X, adding -print -false at the end of find ... -mtime -5 doesn't prevent it from continuing to find additional files with an mtime within the last five days. – user108471 Feb 24 '15 at 20:45
  • I've updated the Answer to provide the optimisation you're looking for (i.e. -quit). On my find this works effectively. – roaima Feb 25 '15 at 11:04
  • Strangely, -quit is not documented in OS X in man find, but it works if used. – user108471 Feb 25 '15 at 15:19
1

If I correctly understood the question this can be done quite simply with

find . -mtime +5 -exec bash -c 'echo "${0%/*}"' {} \; | sort | uniq
  • The parameter expansion inside your echo statement does not correctly grab the directories of interest. If the thing* directories themselves contain directories with files older than 5 days, you won't print the thing* directory correctly. Also this may fail for files with pathological names, but that's probably not a problem in my case. – user108471 Feb 24 '15 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.