You typed rmdir somedir and got back rmdir: failed to remove 'somedir': Directory not empty. Annoying, but this one is honest — rmdir only removes empty directories. If it says the directory isn't empty, it isn't. Your job is to figure out what's still inside and get rid of it.
The culprit is almost always hidden files. A directory can look empty in ls but still have .git, .DS_Store, .env, or a nested folder you forgot about. Docker volume mounts and npm installs leave junk behind all the time.
30-second fix: see what's actually in there
Before nuking anything, look. Run:
ls -la somedir
The -a is the part people forget. Plain ls hides dotfiles. ls -la shows everything, including . and .. which you can ignore.
If you see files listed, that's your answer. Delete them, then rmdir works:
rm somedir/* somedir/.* 2>/dev/null
rmdir somedir
Careful with that glob. somedir/.* will try to match . and .. which is a disaster if you're not careful. The 2>/dev/null swallows the resulting errors, but I don't love it as a habit.
Better idea: use find instead.
5-minute fix: find and delete cleanly
If the directory has nested subdirectories, the glob approach falls apart. Use find:
find somedir -mindepth 1 -delete
rmdir somedir
-mindepth 1 prevents find from trying to delete somedir itself before it's empty. Without that flag, find sometimes chokes on the order of operations.
Want to see what find would delete before you pull the trigger? Drop the -delete and just list:
find somedir -mindepth 1 -print
Run that first. Always. You don't want to find out the hard way that somedir was actually a symlink to /var/log.
15-minute fix: when rmdir still refuses
If rmdir keeps failing after you've cleared everything visible, something is holding the directory. Three usual suspects:
- Immutable attribute set. Check with
lsattr -d somedir. If you see aniin the output, it's immutable. Clear it withchattr -i somedir. This happens on some hardened servers and anything touched by Ansible hardening roles. - A process has the directory as its cwd. Run
lsof +D somedirorfuser -v somedir. If something's using it, kill the process, close the shell, or stop the service. - Mount point. Run
mountpoint somedir. If it says yes, rmdir will never work — you needumount somedirfirst. This bites people who unmount Docker volumes and try to delete the mount source without unmounting.
Check attributes first. It's the fastest of the three:
lsattr -d somedir
lsof +D somedir
mountpoint somedir
The nuclear option: rm -rf
Yes, rm -rf somedir works. No, it's not always the right answer. Here's the trade-off: it deletes everything without asking, ignores permissions (mostly), and doesn't care about hidden files. That's great when you're sure. It's catastrophic when you're not.
Before you type it, do two things:
- Run
pwdand confirm you're where you think you are. An extra space betweenrm -rfand the path has ended careers. - Check for symlinks with
ls -la. A symlink pointing at/plusrm -rf symlink/is a very bad day. GNU coreutils won't follow the symlink itself, but the trailing slash changes things on some systems.
If you're sure, go:
rm -rf somedir
There's no undo. That's the deal.
Why rmdir even exists
Fair question. rmdir is a safety net. On production boxes where a stray rm -rf takes out the wrong folder, rmdir forces you to be deliberate. It won't delete anything you haven't explicitly emptied. Some shops require it in scripts precisely for that reason.
If you're scripting cleanup, prefer find somedir -mindepth 1 -delete && rmdir somedir over rm -rf. It fails loudly when something unexpected shows up, instead of silently eating it.
Common traps
- Trailing slash on symlinks.
rm -rf link/can behave differently thanrm -rf link. Skip the slash. - Wildcards expanding to nothing.
rm somedir/*when the dir has only dotfiles does nothing, and then rmdir still fails. Use find. - NFS and stale handles. On NFS, deleted files can linger if a client holds them open.
lsof +Don the server side usually reveals it. - Case sensitivity. Linux is case-sensitive.
Somedirandsomedirare different folders. Yes, people hit this.
When it's not actually a directory
Sometimes rmdir throws the not-empty error because the path is a file with a misleading name, or a broken mount. Run file somedir and stat somedir. If stat shows a device or inode weirdness, you're not dealing with a normal folder and none of the above applies.
Bottom line: ls -la first, find -delete second, rm -rf when you've earned it. The error is doing you a favor — pay attention to what it's telling you.