When managing directories in Linux, you might encounter situations where you need to clean up multiple subdirectories while preserving one specific directory. This is particularly common in:
- Build systems needing to clean temporary directories
- Log rotation scripts preserving current logs
- Version control cleanup operations
The most straightforward approach uses a combination of find
and rm
commands:
find . -mindepth 1 -maxdepth 1 -type d ! -name "A" -exec rm -rf {} +
Let's analyze what each part does:
.
- Search in current directory-mindepth 1
- Don't include current directory itself-maxdepth 1
- Only look at immediate subdirectories-type d
- Only match directories! -name "A"
- Exclude directory named "A"-exec rm -rf {} +
- Remove matched directories recursively
Using Extended Globbing
If you have bash 4.0+ with extglob enabled:
shopt -s extglob
rm -rf !(A)
With ls and xargs
For systems with limited find
capabilities:
ls -d */ | grep -v "^A/$" | xargs rm -rf
Always test commands with -print
first to see what would be deleted:
find . -mindepth 1 -maxdepth 1 -type d ! -name "A" -print
For production scripts, consider adding additional safeguards:
if [ -d "A" ]; then
find . -mindepth 1 -maxdepth 1 -type d ! -name "A" -exec rm -rf {} +
fi
Matching Multiple Exceptions
To preserve multiple directories:
find . -mindepth 1 -maxdepth 1 -type d ! -name "A" ! -name "B" -exec rm -rf {} +
Pattern Matching
Using wildcards to match directory patterns:
find . -mindepth 1 -maxdepth 1 -type d ! -name "backup_*" -exec rm -rf {} +
For directories with thousands of subdirectories, the -exec +
variant is faster than -exec \;
as it processes multiple files per rm invocation.
When working with Linux file systems, a common administrative task is selectively pruning directories while preserving specific ones. The scenario where we need to keep only directory "A" while removing all other subdirectories occurs frequently in:
- Project cleanup operations
- CI/CD pipeline maintenance
- Server storage optimization
- Automated deployment scripts
Here's the most efficient one-liner solution:
find . -maxdepth 1 -type d ! -name "A" ! -name "." -exec rm -rf {} +
Let's analyze each component:
find . # Start search in current directory
-maxdepth 1 # Limit to immediate subdirectories
-type d # Only match directories
! -name "A" # Exclude directory named "A"
! -name "." # Exclude current directory marker
-exec rm -rf {} + # Execute removal command
Case 1: When dealing with spaces in directory names
find . -maxdepth 1 -type d ! -name "A" -print0 | xargs -0 rm -rf
Case 2: Using extended pattern matching (Bash 4+)
shopt -s extglob
rm -rf !(A)
Always test with -print first to verify targets:
find . -maxdepth 1 -type d ! -name "A" ! -name "." -print
For production systems, consider implementing:
- Dry-run flags in your scripts
- Permission verification
- Backup mechanisms before deletion
Using ls and grep:
ls -d */ | grep -v "^A/" | xargs rm -rf
ZSH users can leverage:
rm -rf ^A/