find files older than X days in bash and delete - bash

I have a directory with a few TB of files. I'd like to delete every file in it that is older than 14 days.
I thought I would use find . -mtime +13 -delete. To make sure the command works as expected I ran find . -mtime +13 -exec /bin/ls -lh '{}' \; | grep '<today>'. The latter should return nothing, since files that were created/modified today should not be found by find using -mtime +13. To my surprise, however, find just spew out a list of all the files modified/created today!

find your/folder -type f -mtime +13 -exec rm {} \;

This works for me.
$ find ./folder_name/* -type f -mtime +13 -print | xargs rm -rf

The simplest solution to this is in #navid's and #gniourf_gniourf's comments. Because it's buried in the comments, I'd like to bring it up to be more visible.
find your/folder -type f -mtime +13 -delete
This avoids any possible issues with spaces and whatnot in the filenames and it doesn't spin up another executable to do the deleting so it should be faster too.
I tried and tested this.

Related

Delete files that are 5 days old using bash script

I currently use a command that searches a directory and deletes 5 day old files.
find /path/to/files* -mtime +5 -exec rm {} \;
I run it from the command line and it works fine. But when I put it in a .sh file it says findĀ /path/to/files*: No such file or directory.
There is only two lines in the shell script:
#! /usr/bin/env bash
find /path/to/files* -mtime +5 -exec rm {} \;
How can I rewrite the script so that it works?
`
The error happens if there are currently no files matching the wildcard, presumably because none have been created since you deleted them previously.
The argument to find should be the directory containing the files, not the filenames themselves, since find will automatically search the directory. If you want to restrict the filenames, use the -name option to specify the wildcard.
And if you don't want to go into subdirectories, use the -maxdepth option.
find /path/to -maxdepth 1 -type f -name 'files*' -mtime +5 -delete
This works:
#! /usr/bin/env bash
find /home/ubuntu/directory -type f -name 'filename*' -mtime +4 -delete
Here is an example:
find /home/ubuntu/processed -type f -name 'output*' -mtime +4 -delete

Log rotation (zipping/deleting) script in Solaris

Had same log rotation files in linux environment and there they work. In Solaris I have problems with running those scrips:
The main purpose of scripts is to delete all logs that are older than 30 days and zip all logs that are older than 5 days. -not -name is used because I want to operate only on rotated log files, for example something.log.20181102 because .log files are current ones and I don't want to touch them.
#!/bin/bash
find ./logs -mindepth 1 -mtime +30 -type f -not -name "*.log" -delete
find ./logs -mtime +5 -not -name "*.log" -exec gzip {} \;
Problems occur with -mindepth and -not because it gives errors:
find: bad option -not
find: [-H | -L] path-list predicate-list
Based on search I have to use -prune somehow in the find, but I am not too sure how to.
If you look at the man page for find(1) on Linux (or gfind(1) on Solaris), you'll see
-not expr
Same as ! expr, but not POSIX compliant.
So you should be able to replace -not with !, though you'll need to escape it from the shell, either with a backslash or with single quotes:
find ... \! -name "*.log" ...
Note that on Solaris, there's a command called logadm which is intended to help you take care of things like this, and may be worth investigating, unless you want to have the exact same behavior on both Solaris and Linux.
With the help of #Danek Duvall and with some searching I got it working:
find ./logs -mtime +30 -type f ! -name "*.log" -exec rm -f {} \;
find ./logs -mtime +5 ! -name "*.log" -exec gzip {} \;
It deletes all log files that are older than 30 days and then zips the ones that are older than 5 days.

Trying to remove a file and its parent directories

I've got a script that finds files within folders older than 30 days:
find /my/path/*/README.txt -mtime +30
that'll then produce a result such as
/my/path/jobs1/README.txt
/my/path/job2/README.txt
/my/path/job3/README.txt
Now the part I'm stuck at is I'd like to remove the folder + files that are older than 30 days.
find /my/path/*/README.txt -mtime +30 -exec rm -r {} \;
doesn't seem to work. It's only removing the readme.txt file
so ideally I'd like to just remove /job1, /job2, /job3 and any nested files
Can anyone point me in the right direction ?
This would be a safer way:
find /my/path/ -mindepth 2 -maxdepth 2 -type f -name 'README.txt' -mtime +30 -printf '%h\n' | xargs echo rm -r
Remove echo if you find it already correct after seeing the output.
With that you use printf '%h\n' to get the directory of the file, then use xargs to process it.
You can just run the following command in order to recursively remove directories modified more than 30 days ago.
find /my/path/ -type d -mtime +30 -exec rm -rf {} \;

Shell script to delete directories older than n days

I have directories named as:
2012-12-12
2012-10-12
2012-08-08
How would I delete the directories that are older than 10 days with a bash shell script?
This will do it recursively for you:
find /path/to/base/dir/* -type d -ctime +10 -exec rm -rf {} \;
Explanation:
find: the unix command for finding files / directories / links etc.
/path/to/base/dir: the directory to start your search in.
-type d: only find directories
-ctime +10: only consider the ones with modification time older than 10 days
-exec ... \;: for each such result found, do the following command in ...
rm -rf {}: recursively force remove the directory; the {} part is where the find result gets substituted into from the previous part.
Alternatively, use:
find /path/to/base/dir/* -type d -ctime +10 | xargs rm -rf
Which is a bit more efficient, because it amounts to:
rm -rf dir1 dir2 dir3 ...
as opposed to:
rm -rf dir1; rm -rf dir2; rm -rf dir3; ...
as in the -exec method.
With modern versions of find, you can replace the ; with + and it will do the equivalent of the xargs call for you, passing as many files as will fit on each exec system call:
find . -type d -ctime +10 -exec rm -rf {} +
If you want to delete all subdirectories under /path/to/base, for example
/path/to/base/dir1
/path/to/base/dir2
/path/to/base/dir3
but you don't want to delete the root /path/to/base, you have to add -mindepth 1 and -maxdepth 1 options, which will access only the subdirectories under /path/to/base
-mindepth 1 excludes the root /path/to/base from the matches.
-maxdepth 1 will ONLY match subdirectories immediately under /path/to/base such as /path/to/base/dir1, /path/to/base/dir2 and /path/to/base/dir3 but it will not list subdirectories of these in a recursive manner. So these example subdirectories will not be listed:
/path/to/base/dir1/dir1
/path/to/base/dir2/dir1
/path/to/base/dir3/dir1
and so forth.
So , to delete all the sub-directories under /path/to/base which are older than 10 days;
find /path/to/base -mindepth 1 -maxdepth 1 -type d -ctime +10 | xargs rm -rf
find supports -delete operation, so:
find /base/dir/* -ctime +10 -delete;
I think there's a catch that the files need to be 10+ days older too. Haven't tried, someone may confirm in comments.
The most voted solution here is missing -maxdepth 0 so it will call rm -rf for every subdirectory, after deleting it. That doesn't make sense, so I suggest:
find /base/dir/* -maxdepth 0 -type d -ctime +10 -exec rm -rf {} \;
The -delete solution above doesn't use -maxdepth 0 because find would complain the dir is not empty. Instead, it implies -depth and deletes from the bottom up.
I was struggling to get this right using the scripts provided above and some other scripts especially when files and folder names had newline or spaces.
Finally stumbled on tmpreaper and it has been worked pretty well for us so far.
tmpreaper -t 5d ~/Downloads
tmpreaper --protect '*.c' -t 5h ~/my_prg
Original Source link
Has features like test, which checks the directories recursively and lists them.
Ability to delete symlinks, files or directories and also the protection mode for a certain pattern while deleting
OR
rm -rf `find /path/to/base/dir/* -type d -mtime +10`
Updated, faster version of it:
find /path/to/base/dir/* -mtime +10 -print0 | xargs -0 rm -f

Using find to delete all subdirectories (and their files)

I'm sure this is straight forward and answered somewhere, but I didn't manage to find what I was looking for. Basically, I'm trying to run a cron script to clear the contents of a given directory every 7 days. So far I have tried the following,
find /myDir -mtime 7 -exec rm -rf {} \;
This however also deletes the parent directory myDir, which I do not want. I also tried,
find /myDir -type f -type d -mtime 7 -delete
which appeared to do nothing. I also tried,
fnd /myDir -type d -delete
which deleted all but the parent directory just as I need. However, a warning message came up reading,
relative path potentially not safe
I'd appreciate if anyone can rectify my script so that it safely deletes all subdirectories in folder.
Many thanks. =)
UPDATE: I decided to go for the following,
find /myDir -mindepth 1 -mtime 7 -delete
Based upon what I learned from all who replied. Again, many thanks to you all.
Try:
find /myDir -mindepth 1 -mtime 7 -exec rm -rf {} \;
What about
cd myDir/ ; find . -type d -delete
assuming that you run this from myDir parent directory.
If you can't guarantee myDir exists, then this is safer:
cd myDir/ && find . -type d -delete
find /myDir -mindepth 1 -mtime 7 -delete
should probably be
find /myDir -mindepth 1 -mtime +7 -delete
(or maybe mtime +6). The + means things 7 days old or older rather than exactly 7 days.

Resources