Disk full, nothing big to delete?
Find Large Files on Linux finds what is on the disk. This page is for when the space is used by something that is no longer there. If df reports IUse% at 100 instead, it is inodes, not bytes: No Space Left on Device with free space.
df says the filesystem is 95% full. du on every directory adds up to half that. Nothing is wrong with either tool: one counts names, the other counts blocks, and a file deleted while a process still had it open has blocks and no name. On 2026-08-28 a 44.6 GB video file deleted on this machine moved du by 44 GB and df by 5. XFCE's thumbnailer, tumblerd, had it open; pkill -x tumblerd gave the space back. lsof +L1 finds that kind of process in one command.
Which Files Are Deleted but Still Holding Space?
Reproduced here on 2026-10-03 (Kali, lsof 4.99.4, bash 5.3.15) on a 200 MB tmpfs mounted inside a user namespace (unshare -rm, no sudo; you appear as root inside it). A background process opens app.log, writes 150 MB and keeps it open, the way a daemon keeps its log:
du dropped to zero. df did not move. lsof +L1 lists open files whose link count is below one, which is the definition of deleted-but-open:
NLINK 0, (deleted), 157,286,400 bytes, held open for writing (4w) by PID 497112 on file descriptor 4. Note exit=1: lsof printed exactly what was asked for and still returned failure. Re-run on 2026-10-03, the same mount given as an absolute path (lsof -w +L1 "$PWD/data") printed the same row and exited 0, so the status depends on how the path is written. Scripts must check its output, never its exit status.
How Do I Free the Space Without a Reboot?
Restart the process, which is the clean answer for a service (systemctl restart). When the process cannot be restarted, empty the file through its descriptor in /proc:
The process keeps running with its descriptor open, now pointing at a zero-length file. The data in that file is gone, so do this to a runaway log, not to a database. Next time, rotate logs with copytruncate or send the service SIGHUP so it reopens the file instead of deleting it out from under the process.
The Script
lsof +L1 on a real desktop prints dozens of rows, mostly tiny memory buffers, and lists one shared file once per process that holds it. Save this as deleted-open-files.sh: it groups by file, skips anything under 1 MB, sorts biggest first, and totals what you would get back.
What Does the Script Print?
On the demo tmpfs with two held files, one with a space in its name, then again after emptying both:
And on this desktop, as a normal user, the same day:
A package upgrade replaced Chrome's binary while 54 Chrome processes were still running the old one (fd txt is the program text itself). Raw lsof +L1 lists that 281 MB file 54 times; the script counts it once. Restarting Chrome is the fix here, and truncating a running binary is not.
It exits 1 when it finds anything, so it works as a check in a disk-alert script: run it as root from cron and mail the output when it fails.
How Do I Find Which Process Holds a Port?
The same namespace trick as above, with four demo listeners and one open client connection:
-i :8099 matches both ends, so the client (bash) shows up beside the server (python3). (LISTEN) marks the owner. -P keeps 8099 numeric and -n skips reverse DNS, both of which matter on a box with many connections. For listeners only, and the ss way of asking, see ss Command Examples. To stop the owner cleanly, Kill Process on Port.
Who Has This Directory Open?
lsof +D walks a directory tree and lists every process using anything inside it, including a process whose working directory is in it (FD cwd). That is what makes umount fail with target is busy:
fuser -vm asks per mount instead of per directory and catches one thing lsof +D missed: PID 497112, which holds an open descriptor (F) on the mount. Its file was deleted and emptied earlier, so it no longer has a name under data/ for +D to find. c is a current directory. Close those, or cd out of the mount, then unmount.
Prerequisites
lsof (apt install lsof, dnf install lsof) and coreutils' numfmt. Run as root to see every process; as a normal user you see only your own, which is still useful on a desktop but misses the services on a server.
Frequently Asked Questions
Why does df show the disk full when du says there is space?
Because a deleted file is still open. rm removes the name, so du stops counting it, but the kernel frees the blocks only when the last process holding the file closes it, so df keeps counting them. Run sudo lsof +L1 to list open files with zero links; the SIZE/OFF column shows how much each one holds. Restarting the process, or truncating the file through /proc/PID/fd/FD, frees the space without a reboot.
How do I find which process is using a port with lsof?
Run sudo lsof -i :PORT -P -n. -i :PORT selects sockets on that port, -P keeps the port numeric and -n skips DNS lookups, which keeps lsof fast on a busy box. The listening row ends in (LISTEN) and the COMMAND and PID columns name the owner. For listeners only, add -sTCP:LISTEN: sudo lsof -iTCP:PORT -sTCP:LISTEN -P -n.
How do I fix umount: target is busy?
Find what still uses the mount with lsof +D /mountpoint or fuser -vm /mountpoint. Look for open files and for processes whose current directory (FD cwd) is inside the mount, which is common: a shell you left cd'd into it is enough. Close the files or cd out, then unmount. umount -l (lazy) detaches the mount immediately but leaves those processes using it, so use it only when you understand what is still holding it.
Is lsof or ss better for checking ports?
ss is faster and ships everywhere with iproute2, so use ss -tulpn for a quick list of listeners. lsof is slower because it walks every process's open files, but it shows the user column, combines ports with files in one tool, and its -i syntax filters by protocol, host and state. On a server with thousands of connections, prefer ss; for answering what does this one process have open, prefer lsof -p PID.
Why does lsof print warnings about docker or overlay file systems?
lsof tries to stat every mounted filesystem, and as a normal user it cannot stat docker's overlay mounts or network namespaces under /run/docker. The warnings say the output may be incomplete for those mounts and are otherwise harmless. Add -w to suppress them, or run lsof as root, which can stat everything.
The disk space warning script tells you a filesystem is filling before df hits 100%, and The Production Bash Toolkit bundles its health checks (disk, memory, load, services, HTTP) ShellCheck-clean.
Part of the bash snippets collection
Related Scripts
- Find Large Files on Linux — what is actually using the disk, by directory and by file
- ss Command Examples — listeners and connections, faster than lsof on busy servers
- Kill Process on Port — stop the owner lsof found, gracefully first
- No Space Left on Device With Free Space — when the disk is full of inodes, not bytes