124

I write below command to delete all files that are older than 7 days, but it doesn't work:

find /media/bkfolder/ -mtime +7 -name'*.gz' -exec rm {} \;

How can I remove these files?

1
  • 11
    There should be a space between name and '*.gz'.
    – Jos
    Feb 24, 2015 at 9:25

3 Answers 3

217

As @Jos pointed out you missed a space between name and '*.gz'; also for speeding up the command use -type f option to running the command on files only.

So the fixed command would be:

find /path/to/ -type f -mtime +7 -name '*.gz' -execdir rm -- '{}' \;

Explanation:

  • find: the unix command for finding files/directories/links and etc.
  • /path/to/: the directory to start your search in.
  • -type f: only find files.
  • -name '*.gz': list files that ends with .gz.
  • -mtime +7: only consider the ones with modification time older than 7 days.
  • -execdir ... \;: for each such result found, do the following command in ....
  • rm -- '{}': remove the file; the {} part is where the find result gets substituted into from the previous part. -- means end of command parameters avoid prompting error for those files starting with hyphen.

Alternatively, use:

find /path/to/ -type f -mtime +7 -name '*.gz' -print0 | xargs -r0 rm --

From man find:

-print0 
      True; print the full file name on the standard output, followed by a null character 
  (instead of the newline character that -print uses). This allows file names that contain
  newlines or other types of white space to be correctly interpreted by programs that process
  the find output. This option corresponds to the -0 option of xargs.

Which is a bit more efficient, because it amounts to:

rm file1 file2 file3 ...

as opposed to:

rm file1; rm file2; rm file3; ...

as in the -exec method.


An alternative and also faster command is using exec's + terminator instead of \;:

find /path/to/ -type f -mtime +7 -name '*.gz' -execdir rm -- '{}' +

This command will run rm only once at the end instead of each time a file is found and this command is almost as fast as using -delete option as following in modern find:

find /path/to/ -type f -mtime +7 -name '*.gz' -delete
3
  • 11
    Why wouldn't I go straight with -delete at the end? Why mess with the + or \;?
    – rain01
    Jan 5, 2019 at 2:46
  • 6
    @rain01 plz read unix.stackexchange.com/q/167823/72456 Jan 14, 2019 at 17:49
  • I think when using find to do a batch deletion like all *.gz files, it would be important to make use of -maxdepth. The Find command seems to be recursive by default, and it will search all child directories for a matching pattern. This may be unwanted behavior, so it would be a good idea to use -maxdepth 1 Nov 16, 2022 at 16:45
14

Be careful removing files with find. Run the command with -ls to check what you are removing

find /media/bkfolder/ -mtime +7 -name '*.gz' -ls . Then pull up the command from history and append -exec rm {} \;

Limit the damage a find command can do. If you want to remove files from just one directory, -maxdepth 1 prevents find from walking through subdirectories or from searching the full system if you typo /media/bkfolder /.

Other limits I add are more specific name arguments like -name 'wncw*.gz', adding a newer-than time -mtime -31, and quoting the directories searched. These are particularly important if you are automating cleanups.

find "/media/bkfolder/" -maxdepth 1 -type f -mtime +7 -mtime -31 -name 'wncw*.gz' -ls -exec rm {} \;

1
  • This answer is more safe. Thanks for this.
    – palerdot
    Aug 10, 2020 at 14:06
14

for the completeness: you may also use -delete

find /some/where/ -name '*.log' -type f -mtime +7 -delete

this way you don't run a command per file.

1
  • 1
    This is the best answer. Well done for placing the "-delete" portion at the end of the line. I strongly suggest anyone considering this method reads the man page prior to implementation. Dec 7, 2022 at 15:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.