How to Safely Delete Files Matching a Pattern Using find and xargs in Bash


6 views

When trying to delete VMware log files using:

find . -name vmware-*.log | xargs rm

You'll encounter issues with filenames containing spaces. The command breaks because xargs by default splits input on whitespace.

Here are several robust approaches:

1. Using find's -exec Option

The most straightforward solution:

find . -name "vmware-*.log" -exec rm {} \;

Or more efficiently with + terminator:

find . -name "vmware-*.log" -exec rm {} +

2. Using xargs with -0 Option

Combine find with -print0 and xargs -0:

find . -name "vmware-*.log" -print0 | xargs -0 rm

This handles all special characters including spaces and newlines.

3. Using Shell Globstar (Bash 4+)

For simpler cases in modern Bash:

shopt -s globstar
rm **/vmware-*.log

For more complex operations:

Preview Before Deletion

find . -name "vmware-*.log" -exec echo rm {} \;

Delete Files Older Than 30 Days

find . -name "vmware-*.log" -mtime +30 -exec rm {} +

Combining Multiple Patterns

find . $-name "vmware-*.log" -o -name "*.vmdk"$ -exec rm {} +
  • Always test with -exec echo or -print first
  • Consider using -i option with rm for interactive deletion
  • For system-wide operations, run as root carefully

When working with the find command in bash, one common issue arises when dealing with filenames containing spaces. The default behavior of piping to xargs can break these filenames into multiple arguments, causing the rm command to fail.

The command you're using:

find . -name vmware-*.log | xargs rm

fails because:

  • xargs splits input by whitespace by default
  • Each space in a path creates a separate argument
  • rm receives broken file paths

Here are several reliable approaches to handle this scenario:

1. Using find's -exec Parameter

The most straightforward solution is to use find's built-in execution capability:

find . -name "vmware-*.log" -exec rm {} \;

Or more efficiently with +:

find . -name "vmware-*.log" -exec rm {} +

2. Proper xargs Usage

If you prefer using xargs, use the -0 option with find -print0:

find . -name "vmware-*.log" -print0 | xargs -0 rm

This approach:

  • Uses null character as separator (-print0/-0)
  • Properly handles all special characters in filenames
  • Works with any number of files

3. Using Shell Globbing (Simple Cases)

For simpler cases where you're in the target directory:

rm vmware-*.log

Or recursively with bash 4+:

shopt -s globstar
rm **/vmware-*.log

Preview Before Deletion

Always test with -ls or -print first:

find . -name "vmware-*.log" -ls

Handling Very Large File Sets

For directories with thousands of files, use -delete (find 4.2.3+):

find . -name "vmware-*.log" -delete

For different scenarios:

# Delete files older than 30 days
find . -name "vmware-*.log" -mtime +30 -exec rm {} +

# Delete files larger than 100MB
find . -name "vmware-*.log" -size +100M -exec rm {} +

# Delete empty log files
find . -name "vmware-*.log" -empty -exec rm {} +