I need to find files modified in the last month in one directory and copy to another directory, but with this command I only find the ones modified in last 31 days, not in the last month.

/usr/bin/find $SOURCE_DIR -maxdepth 1 -type f -name 'files*.pdf' -mtime -31 -exec cp -p {} $DEST_DIR`date +"%B_%Y"` \;

I need files modified last month for example: files modified in January, in February , ...Any suggestion?


3 Answers 3


@SmileDeveloper is on the right track, but it actually turns out to be pretty tricky:

$ cd "$(mktemp --directory)"
$ touch --date="$(date --date="$(date --rfc-3339=date | cut --characters=-7)-01 - 1 day" --rfc-3339=second)" last-day-of-last-month
$ touch --date="$(date --date="$(date --rfc-3339=date | cut --characters=-7)-01 - 1 second" --rfc-3339=second)" end-of-last-month
$ touch --date="$(date --rfc-3339=date | cut --characters=-7)-01" start-of-current-month
$ touch --date="$(date --date="$(date --rfc-3339=date | cut --characters=-7)-01 + 1 month - 1 second" --rfc-3339=second)" end-of-current-month
$ touch --date="$(date --date="$(date --rfc-3339=date | cut --characters=-7)-01 + 1 month" --rfc-3339=second)" start-of-next-month
$ stat --printf '%y\t%n\n' ./* | sort --key=1
2020-06-30 00:00:00.000000000 +1200 ./last-day-of-last-month
2020-06-30 23:59:59.000000000 +1200 ./end-of-last-month
2020-07-01 00:00:00.000000000 +1200 ./start-of-current-month
2020-07-31 23:59:59.000000000 +1200 ./end-of-current-month
2020-08-01 00:00:00.000000000 +1200 ./start-of-next-month
$ find . -mindepth 1 -newermt "$(date --rfc-3339=date | cut --characters=-7)-01 - 1 second" -not -newermt "$(date --rfc-3339=date | cut --characters=-7)-01 + 1 month - 1 second"

Basically the last command gives you the range from the last second of last month (exclusive) to the last second of the current month (inclusive). If you want absolute precision that probably gets even uglier, because find doesn't seem to have a way to select an inclusive start datetime and exclusive end datetime, unlike most programming languages.

Hopefully you don't have to worry about time zones within all this as well!


Current month (from first day)

/usr/bin/find $SOURCE_DIR -maxdepth 1 -type f -name 'files*.pdf' -newermt "$(date +%y-%m-1)" -exec cp -p {} $DEST_DIR`date +"%B_%Y"` \;

First day of last month to now:

/usr/bin/find $SOURCE_DIR -maxdepth 1 -type f -name 'files*.pdf' -newermt "$(date -d "$(date +%y-%m-1) - 1 month" +%y-%m-%d)" -exec cp -p {} $DEST_DIR`date +"%B_%Y"` \;

First day of last month to last day of last month:

/usr/bin/find $SOURCE_DIR -maxdepth 1 -type f -name 'files*.pdf' -newermt "$(date -d "$(date +%y-%m-1) - 1 month" +%y-%m-%d)" -not -newermt "$(date +%y-%m-1)" \;


Do not use mtime, because mtime search for files that are modified in 24*n, and does not start at the beginning of the day.

  • Since you're using -newermt, read up on -daytime too Jul 12, 2020 at 8:47

I seem to use find -printf a lot for these things.

$ which month_files
month_files () {
        find . -type f -printf "%TY-%Tm\t%p\n" | grep ^$1 | cut -f2

# example run on my ~/.cache directory
$ month_files 2020-05 | wc
   1007    1007   49917

Now you can process those files however you like. For example,

mkdir /target/2020-05
month_files 2020-05 | xargs -d"\n" -I % cp % /target/2020-05/

The -I will force -L 1 (one execution per line). Specifically for the cp command, you can get better efficiency by using

month_files 2020-05 | xargs -d"\n" cp --target-directory /target/2020-05/

I'm assuming none of the filenames have a newline in them. I don't really hold with that kind of nonsense on my systems, I mean spaces and some special characters are one thing, newlines are quite another. (Or, with apologies to Ian Fleming, "spaces are happenstance; special characters are coincidence, newlines are enemy action"!)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .