4

I have to make a cronjob to remove files older than 99 days in a particular directory but I'm not sure the file names were made by trustworthy Linux users. I must expect special characters, spaces, slash characters, and others.

Here is what I think could work:

find /path/to/files -mtime +99 -exec rm  {}\;

But I suspect this will fail if there are special characters or if it finds a file that's read-only, (cron may not be run with superuser privileges). I need it to go on if it meets such files.

Emil Vikström
  • 90,431
  • 16
  • 141
  • 175
user1469220
  • 41
  • 1
  • 1
  • 2

4 Answers4

11

When you use -exec rm {} \;, you shouldn't have any problems with spaces, tabs, returns, or special characters because find calls the rm command directly and passes it the name of each file one at a time.

Directories won't' be removed with that command because you aren't passing it the -r parameter, and you probably don't want too. That could end up being a bit dangerous. You might also want to include the -f parameter to do a force in case you don't have write permission. Run the cron script as root, and you should be fine.

The only thing I'd worry about is that you might end up hitting a file that you don't want to remove, but has not been modified in the past 100 days. For example, the password to stop the autodestruct sequence at your work. Chances are that file hasn't been modified in the past 100 days, but once that autodestruct sequence starts, you wouldn't want the one to be blamed because the password was lost.

Okay, more reasonable might be applications that are used but rarely modified. Maybe someone's resume that hasn't been updated because they are holding a current job, etc.

So, be careful with your assumptions. Just because a file hasn't been modified in 100 days doesn't mean it isn't used. A better criteria (although still questionable) is whether the file has been accessed in the last 100 days. Maybe this as a final command:

 find /path/to/files -atime +99 -type f -exec rm -f {}\;

One more thing...

Some find commands have a -delete parameter which can be used instead of the -exec rm parameter:

 find /path/to/files -atime +99 -delete

That will delete both found directories and files.

One more small recommendation: For the first week, save the files found in a log file instead of removing them, and then examine the log file. This way, you make sure that you're not deleting something important. Once you're happy thet there's nothing in the log file you don't want to touch, you can remove those files. After a week, and you're satisfied that you're not going to delete anything important, you can revert the find command to do the delete for you.

Community
  • 1
  • 1
David W.
  • 105,218
  • 39
  • 216
  • 337
  • David W. ok, but the path to files will not be to some guys directory, i believe (or hope it isn't) since i will not really be there. so here is what i can gather so far: find /path/to/files -atime +99 -execdir rm -f {}\; – user1469220 Jun 20 '12 at 13:44
  • Using `-execdir` won't work. It will execute the `rm` command from the directory where the file is found, but the `{}` won't be trimmed, so the file name will be invalid. By the way, I added the `-type f` to the command, so we are only talking about files. – David W. Jun 20 '12 at 14:56
  • @user1469220 One more thing. It's not a standard Unix find parameter, but it is available on many find commands. You might be able to use the `-delete` parameter and forget about the `-exec` entirely. See my comments in my answer above. – David W. Jun 20 '12 at 14:57
1

If you run rm with the -f option, your file is going to be deleted regardless of whether you have write permission on the file or not (all that matters is the containing folder). So, either you can erase all the files in the folder, or none. Add also -r if you want to erase subfolders.

And I have to say it: be very careful! You're playing with fire ;) I suggest you debug with something less harmful likfe the file command.

You can test this out by creating a bunch of files like, e.g.:

touch {a,b,c,d,e,f}

And setting permissions as desired on each of them

Miquel
  • 15,405
  • 8
  • 54
  • 87
  • well, i can handle a little fire here and there, i got some virtual machines in my desktop at home that i can play with without consequence. but anyway , what if there are special characters like embedded newlines in the filenames? – user1469220 Jun 20 '12 at 13:03
  • I don't think you can have newlines in a file, and this solution should also handle whitespaces. Why don't you give it a go and report if there's any problems? – Miquel Jun 20 '12 at 14:30
1

You should use -execdir instead of -exec. Even better, read the full Security considerations for find chapter in the findutils manual.

lanzz
  • 42,060
  • 10
  • 89
  • 98
  • Since the OP is passing the file name directly to the `rm` command, there is no issue with using `-exec` instead of `-execdir`. A file starting with a dash or has a space in it won't cause any problems. There would be a problem if the OP was using `sh -c rm`. Best bet is to use `-delete` if it's available. – David W. Jun 20 '12 at 15:13
1

Please, always use rm [opts] -- [files], this will save you from errors with files like -rf wiich would otherwise be parsed as options. When you provide file names, then end all options.

MBO
  • 30,379
  • 5
  • 50
  • 52