1

This is related to my last question [How to always print an output with certain number of digits using AWK.

So, now I have the following command; the goal is to copy bunch of files into different directories based on certain factors:

find . -mtime -5 -type f -name '*data.txt' -printf "cp -p %p "/tmp/HTTPBackup/"%Td"/"\n"

This outputs:

cp -p ./32982_96xxdata.txt /tmp/HTTPBackup/09/
cp -p ./32312_96xxdata.txt /tmp/HTTPBackup/11/
cp -p ./32191_96xxdata.txt /tmp/HTTPBackup/07/

Now, how do I execute all these lines printed to the screen? Do I keep -printf and add -exec?

Ex:

find . -mtime -5 -type f -name '15692_96xxdata.txt' -printf "cp -p %p "/tmp/HTTPBackup/"%Td"/"\n" -exec {} \;

It didn't work; It was complaining that the permission was denied even though I own the file with 644 permissions - a simple copy works just fine.

cp -p ./15692_96xxdata.txt /tmp/http_backups/09/
find: ‘./15692_96xxdata.txt’: Permission denied

or replace -printf with -exec somehow? Not sure how to even try this.

Thank you!

7
  • Just pipe it to a shell by appending | sh Jul 11, 2019 at 20:52
  • @L. Scott Johnson - just to make sure: find . -mtime -5 -type f -name '*data.txt' -printf "cp -p %p "/tmp/HTTPBackup/"%Td"/"\n" | sh - that's all I need to do? So, it doesn't really create a new shell script or anything, and all done in the background, right? I'd eventually need to set up a daily cron job to process new files each night. Thanks!
    – GA_train
    Jul 11, 2019 at 22:14
  • (1) -exec {} means “run the .txt file as a script”.  That’s why it was giving you a permission error — you don’t have execute permission on your .txt files.  Don’t use -exec {} unless your files are scripts; and even then, think hard about what you’re doing before you do it.  (2) Piping the output of find into sh should work and be safe if all your filenames are “normal”; i.e., made up of letters, digits, _ and ..  If filenames can contain unusual characters, it can fail, perhaps harmfully. … (Cont’d) Jul 12, 2019 at 0:24
  • (Cont’d) …  (3) It seems a shame not to use find’s printf capability. But you can do what you want safely if you have the stat command and you’re willing to use it. Jul 12, 2019 at 0:24
  • 1
    @G-Man Seems like an -execf action would be handy Jul 13, 2019 at 0:07

2 Answers 2

2

You need those -p, %p, /tmp/HTTPBackup/%Td to be passed after %-expansion as separate arguments to the cp command. xargs could be used to do that splitting safely¹ if you print those arguments NUL-delimited (0 being the only byte value that can't occur in a file path or executed command argument):

find . -name '*data.txt' -mtime -5 -type f \
  -printf '-p\0%p\0/tmp/HTTPBackup/%Td/\0' |
  xargs -r0 -n3 cp

Or:

find . -name '*data.txt' -mtime -5 -type f \
  -printf '%p\0/tmp/HTTPBackup/%Td/\0' |
  xargs -r0 -n2 cp -p

¹ using a directory with a fixed name (HTTPBackup) in a world writable directory such as /tmp can be unsafe though.

0

To have a regular answer I quote some comments given to the question.

Just pipe it to a shell by appending | sh. just to make sure:

find . -mtime -5 -type f -name '*data.txt' -printf "cp -p %p "/tmp/HTTPBackup/"%Td"/"\n" | sh
  • (1) -exec {} means “run the .txt file as a script”.  That’s why it was giving you a permission error — you don’t have execute permission on your .txt files. Don’t use -exec {} unless your files are scripts; and even then, think hard about what you’re doing before you do it.
  • (2) Piping the output of find into sh should work and be safe if all your filenames are “normal”; i.e., made up of letters, digits, _ and ..  If filenames can contain unusual characters, it can fail, perhaps harmfully.

You must log in to answer this question.

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