Copy and Delete

2.2k views Asked by At

Ok, I am new to ubuntu. I have 200,000 files that I need to go through and archive files that have not been updated in 30days.

find . -type f -mtime +30

Done.

Then I need to copy them to a location while keeping their dir structure past the current ./ This is because the file structure is part of the uniqueness of each file. I may have 200 files called sum however FunRun/Sum and Smoke/Sum are two different things.

find . -type f -mtime +30 -exec cp --parents '{}' /home/me/backup \;

Done. But that does not delete them... Well mv is a cp with delete. But MV does not have --parents switch.

So I tried

find . -type f -mtime +30 -exec cp --parents '{}' /home/me/backup \; && rm
for file in 'find . -type f -mtime +30' do sudo cp $file --parents '{}' /home/me/backup \; && sudo rm $file; done

No go. So I was playing with creating a list of files and use it like old school batch files. Problem is the list takes a long time to make and I would like to automate this process. So I searched and tested nothing worked. So either a one-line bash script is a lost cause and will need to write a python script to do it or you guys can help. So I figured I would ask here and see how it goes over the weekend and test on monday.

Thanks for your help.

1

There are 1 answers

8
abarnert On BEST ANSWER

Most of what you're doing looks like shotgun debugging attempts—just changing random things without really knowing what they mean. You should really read through a tutorial on find, and maybe one on bash scripting.


Anyway, you can string together multiple actions on a single find command. Even multiple -exec actions if you want. So:

find . -type f -mtime +30 -exec cp --parents '{}' /home/me/backup \; -exec rm '{}' \;

Or, more simply:

find . -type f -mtime +30 -exec cp --parents '{}' /home/me/backup \; -delete

Or, of course, you could write your own two-line shell script that calls cp --parents with all of its arguments, then calls rm with all but its last argument, and just -exec that.


If you want to do the for loop, you can do that… although xargs would probably make for sense than doing them one by one, let's try it your way:

  • You're not calling find at all; single quotes mark literal strings. If you want to execute a string as a command and get the results, you want backticks. Or, better, $(…).
  • A one-liner for loop needs a semicolon before the do.
  • You've added sudo, which wasn't in your find commands, so I doubt you want it here either.
  • Using $file without quotes is a bad idea if you have any files with, say, spaces in the names.
  • The '{}' and \; are going to pass literal {} and ; strings to cp. So, you're asking it to copy $file, {}, and /home/me/backup to ;. That doesn't make any sense. The find command has special uses for those things, but cp doesn't. If you're using '{}' to try to pass the filename, you're already doing that with $file.

So:

for file in $(find . -type f -mtime +30); do cp "$file" --parents /home/me/backup && sudo rm "$file"; done