1

Say I have these files in dir1:

-rw-r--r--  1 user user  10240 Jul  2 11:54 10_data.txt
-rw-r--r--  1 user user  36048 Jul  4 11:56 95_data.txt
-rw-r--r--  1 user user  35634 Jul  7 11:56 01_data.txt
-rw-r--r--  1 user user  10630 Jul  9 11:56 19_data.txt
-rw-r--r--  1 user user  35476 Jul  9 11:57 93_data.txt

I want to be able to copy these files based on their timestamps, specifically the day of the month (2, 4, 7 and 9).

Ex:

copy 10_data.txt into a directory called 02
copy 19_data.txt into a directory called 09
copy 93_data.txt into a directory called 09

Destination directories (01, 02, 03 , etc.) would already exist, so no need to create them or anything. I plan to run this as a cron job daily after midnight.

Can I use find for this task along with (date +%d) or something like that?

Thank you!

3 Answers 3

1

If you have zsh available, you could do this with its zstat module:

zmodload zsh/stat
for f in *.txt
do
  cp -p -- "$f" $(zstat -F %d +mtime "$f")/
done

The zstat -F %d +mtime command asks for the formatted output (-F %d) of the day-of-the-month of the files' modification times. The resulting decimal number is in the range 01 to 31, and is used as the target for the cp command.

2
  • Nice use of -- to insulate against filenames begining with a hyphen. I borrowed that to improve my answer. In return, may I suggest -p? By default, cp alters the modification date of the file, which is an important piece of the OP's stated problem. Using -p preserves the modification date, which in turn makes it easier to confirm the files were copied to the correct directories.
    – Jim L.
    Commented Jul 9, 2019 at 19:12
  • Great suggestion, Jim L; thank you! I've incorporated it.
    – Jeff Schaller
    Commented Jul 9, 2019 at 19:22
0

stat is your friend for finding out when a file was modified, or its size, or most any of the file attributes that ls would display.

On FreeBSD, for example, stat -f %Sm -t %d -- foo will show you the day of the month when file foo was last modified, which appears to be what you are after.

No need for find, you can iterate over the files directly, such as in this bash example:

for f in *; do
  d=$(stat -f %Sm -t %d -- "$f")
  cp -p -- "$f" $d/
done

Responding to your comment that your target OS is RedHat, it appears that RedHat's stat utility does not have the formatting flexibility that FreeBSD's has. You can compare the man pages here.

You may find the command date -r foo "+%d" a suitable substitute. The relevant line of the script would then become:

  d=$(date -r "$f" "+%d")
6
  • 1
    You might indicate whether this relies on the GNU stat or some other implementation.
    – Jeff Schaller
    Commented Jul 9, 2019 at 18:16
  • @Jeff-Schaller Good idea. Thank you.
    – Jim L.
    Commented Jul 9, 2019 at 18:33
  • I am trying to do this on a RHEL system
    – GA_train
    Commented Jul 9, 2019 at 18:34
  • @GA_t man stat should show you what you need to know. You can play with the stat command manually until you find the options that work for your OS. Then just plug that syntax into the script.
    – Jim L.
    Commented Jul 9, 2019 at 18:37
  • This "RHEL" comment indicates that the question could use a Linux tag, in order to focus any other answerers on the runtime environment that applies.
    – Jeff Schaller
    Commented Jul 9, 2019 at 19:23
0

You may try like this. I've tested. It should work

cp `ls -ltrh *txt  | awk '{if($7=2){print $NF}}'` `ls -ltrh *txt  | awk '{print $7}'`

I've considered for only day of 2 and directory is on same path. Kindly add other dates and if the directory is another folder then add that as well.

Another assumption is that there is no space in file name.

2
  • 2
    careful if someone does touch "foo bar.txt"
    – Jeff Schaller
    Commented Jul 9, 2019 at 18:14
  • Yes. code snippet wont work on that case. Need to handle that. Nice input btw @JeffSchaller Commented Jul 9, 2019 at 18:16

You must log in to answer this question.

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