How to find and delete directory recursively on Linux or Unix-like system

I type ‘find . -type d -iname foo -delete‘ command to find all foo directories and delete them. However, I am getting an error message that read as find: cannot delete './hourly.4/data/foo': Directory not empty on Linux server. How do I find and delete directories based on find command output on Linux or Unix-like system recursively?

Delete directories based on find command output
The -delete option remove the DIRECTORY(ies), if they are empty. You need to use the -exec option to delete all directories and its contents. The syntax is as follows.

ADVERTISEMENTS

Find command syntax to delete directory recursively

Try the find command:
find /dir/to/search/ -type d -name "dirName" -exec rm -rf {} +
Another option is as follows to recursively remove folders on Linux or Unix:
find /dir/to/search/ -type d -name "dirName" -exec rm -rf \;

Warning: Be careful with the rm command when using with find. You may end up deleting unwanted data.

Find will execute given command when it finds files or dirs. For example:
find . -type d -name "foo" -exec rm -rf {} +
OR
find . -type d -name "bar" -exec rm -rf "{}" \;
Sample outputs:

removed './daily.0/bar/.cache/motd.legal-displayed'
removed directory './daily.0/bar/root/.cache'
removed './daily.0/bar/.lesshst'
removed './daily.0/bar/.viminfo'
removed './daily.0/bar/.vim/.netrwhist'
removed directory './daily.0/bar/root/.vim'
removed './daily.0/bar/root/.bashrc'
removed './daily.0/bar/.ssh/authorized_keys'
removed directory './daily.0/bar/root'
removed directory './daily.0/bar/var/spool/cron/crontabs'

You can find directories that are at least four levels deep in the working directory /backups/:
find /backups/ -type d -name "bar" -depth +4 -print0 -exec rm -rf {} +

Finding and deleting directory recursively using xargs

The syntax is as follows to find and delete directories on Linux/Unix system. For example, delete all empty directories:
find /path/to/dir/ -type d -empty -print0 | xargs -0 -I {} /bin/rm -rf "{}"
In this example, remove all foo directories including sub-diretories in /backups/ folder:
find /backups/ -type d -name "foo*" -print0 | xargs -0 -I {} /bin/rm -rf "{}"
The second command is a secure version. It is fast too, and it deals with weird directory names with white spaces and special characters in it:

  • foo bar
  • Foo _ *bar
  • | Foo _ *bar |!

Hence, I would like readers to use the following syntax:
find /path/to/search/ -name "pattern" -print0 | xargs -0 -I {} /bin/rm -rf "{}"
Where find command options are:

  • -name "pattern" : Base of file name that matches shell pattern pattern. For example, foo, Foo*3 and so on.
  • -print0 : Show the full file name on the standard output, followed by a null character. 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

And xargs command options are:

  • -0 : Input items given by find are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or backslashes. The GNU find -print0 option produces input suitable for this mode.
  • -I {} : {} in the initial-arguments with names read from standard input. For example, dir names given by find command./li>
  • /bin/rm -rf "{}" : Run rm command that remove files or directories passed by {}.

Shell script to recursively remove backups older than 30 days

Here is my sample script that removes older weekly backup of my VM tarballs stored in the following format:

drwxr-xr-x 2 root root 292 Aug  2 11:14 08-02-2020
drwxr-xr-x 2 root root 292 Aug  9 10:36 08-09-2020
drwxr-xr-x 2 root root 292 Aug 16 10:44 08-16-2020
drwxr-xr-x 2 root root 292 Aug 23 10:48 08-23-2020
drwxr-xr-x 2 root root 292 Aug 30 10:52 08-30-2020
drwxr-xr-x 2 root root 292 Sep  6 10:53 09-06-2020
drwxr-xr-x 2 root root 292 Sep 13 10:54 09-13-2020

Delete VM backup directories based on find command output

#!/bin/bash
# Purpose: Basic shell script to remove older VM backups tarballs
# Author: Vivek Gite {https://www.cyberciti.biz/} under GPL v2.0+
# -----------------------------------------------------------------
 
# Get today's date and set log file
DEST="/backups/VMs" 
failed="false"
_find="/usr/bin/find"
log="/tmp/backup-roation.$$.txt"
 
# Get access to mobile push API for sysadmin and developers 
# See https://www.cyberciti.biz/mobile-devices/android/how-to-push-send-message-to-ios-and-android-from-linux-cli/
source /root/bin/cli_app.sh
 
# Die if $DEST not found 
[ ! -d "$DEST" ] && exit 1
 
#
# Find and delete all directory recursively if they are older than 30 days
# -mtime 30 means file's data was last modified n*24 hours ago 
#           (30*24 = 720 hours i.e. 30days ago)
#
$_find  $DEST -type d -mtime +30 -print0 | xargs -I dir -0 /bin/rm -rvf "dir" >"${log}"
[ $? -ne 0 ] && failed="true"
 
#
# Send email and push status to sysadmin mobile 
#
if [ "$failed" == "true" ]
then
	push_to_mobile "$0" "Alert backup rotation failed - $HOSTNAME [EC2]. See email for details."
	mail -A "$log" -s "Backup rotation failed $HOSTNAME [EC2]" -r webmaster@cyberciti.biz alert@somewhere-tld <<< "$0 script cached errors."
else
	push_to_mobile "$0" "Monthly backup rotation successful $HOSTNAME [EC2]"
	mail -A "$log" -s "Backup rotation  successful $HOSTNAME [EC2]" -r webmaster@cyberciti.biz alert@somewhere-tld <<< "$0 script ran successfully."
fi
 
# Remove log file if found
[ -f "$log" ] && /bin/rm -f "$log"

See “How to push/send message to iOS and Android from Linux CLI” for more information.

Conclusion

You learned how to search and delete a directory recursively when using Linux or Unix-like operating system.

🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source/DevOps topics:
CategoryList of Unix and Linux commands
File Managementcat
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilitiesdig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04

ADVERTISEMENTS
7 comments… add one
  • Jouni "rautamiekka" Järvinen Jun 21, 2017 @ 7:50

    I’d escape the curly brackets with §'{}’§ instead of leaving them §{}§ or §”{}”§ cuz that leaves no room for mistakes and, as a minor point, provides a speed boost.

  • Raphael Jun 21, 2017 @ 8:33

    rm -rf $(find . -type d -name "dirName")

    • Raphael Jun 21, 2017 @ 8:36

      This command is also possible and a little bit shorter

  • Dean Sep 16, 2020 @ 7:27

    My cpanel always compromised, hacker oftenly store phishing folder “adfs” or “admincp”. I want to automatically delete those folder daily, will this works with cron?
    will simply add ” find /myusername -type d -name “adfs” -exec rm -rf \;” works?
    I still afraid to try since I dont want to delete unwanted folder.

    • 🐧 Vivek Gite Sep 16, 2020 @ 13:12

      A better solution is to secure your server. If a hacker can create folders on the production box, they are doing much more damage. Hence, secure your server. Fix root of problem.

  • NathanTP Sep 16, 2020 @ 19:00

    Dude the script is fascinating. I learned something new about pushing messages to a mobile phone from shell scripts. This will come handy for sure.

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.