Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advice on using crontab with bash

Tags:

bash

cron

I want to make a cron job that checks if a folder exists, and it if does to delete all the contents of that folder. For example, I know that the following will delete the contents of my folder in using cron:

0 * * * * cd home/docs/reports/;rm -r *

However, I realized that if the folder is removed (or the wrong file path is given) instead of the contents of that folder being deleted, cd fails and all files are deleted on my operating system. To prevent this from happening (again) I want to check for the existence of the folder first, and then to delete the contents. I want to do something like the following, but I'm not sure how to use a bash script with cron.

if [ -d "home/docs/reports/" ]; then
    cd home/docs/reports/;rm -r *
fi

I'm new to bash and cron (in case it is not obvious).

like image 635
djq Avatar asked Jul 27 '26 07:07

djq


2 Answers

I think cron uses /bin/sh to execute commands. sh is typically a subset of bash, and you're not doing anything bash-specific.

Execute the rm command only if the cd command succeeds:

0 * * * * cd home/docs/reports/ && rm -r *

NOTE Please wait a few minutes while I test this. If this note is gone, I've tried it and it works.

Yes, it works. (Note that testing whether the directory exists is less reliable; it's possible that the directory exists but you can't cd into it, or it might cease to exist between the test and the cd command.)

But actually you don't need to use a compound command like that:

 0 * * * * rm -r home/docs/reports/*

Still the && trick, and the corresponding || operator to execute a second command only if the first one fails, can be very useful for more complicated operations.

(Did you mean /home/docs rather than home/docs? The latter will be interpreted relative to your home directory.)

Though this worked ok when I tried it, use it at your own risk. Any time you combine rm -r with wildcards, there's a risk. If possible, test in a directory you're sure you don't care about. And you might consider using rm -rf if you want to be as sure as possible that everything is deleted. Finally, keep in mind that the * wildcard doesn't match files or directories whose names start with ..

#include <stddisclaimer.h>

EDIT :

The comments have given me a better understanding of what you're trying to do. These are files that users are going to download shortly after they're created (right?), so you don't want to delete anything less than, say, 5 minutes old.

Assuming you have GNU findutils, you can do something like this:

0 * * * *  find /home/docs/reports/* -cmin +5 -delete 2>/dev/null

Using the -delete option to find means you're deleting files and/or directories one at a time, not deleting entire subtrees; the main difference is that an old directory with a new file in it will not be deleted. Applying -delete to a non-empty directory will fail with an error message.

Read the GNU find documentation (info find) for more information on the -cmin and -delete options. Note that -ctime operates on the time of the last status change of the file, not its creation time (Unix doesn't record file creation times). For your situation, it's likely to be the same.

(If you omit the /* on the path, it will delete the reports directory itself.)

like image 62
Keith Thompson Avatar answered Jul 30 '26 10:07

Keith Thompson


Wrap your entire command (including the if logic) into a script.sh.

Specify #!/bin/bash at the top of your script.

Make it executable:

chmod +x script.sh

Then specify the full path of the script in your cron job.

like image 25
merlin2011 Avatar answered Jul 30 '26 08:07

merlin2011



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!